



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Three techniques for automatic memory management in garbage collection: reference counting, stop and copy, and mark-sweep. It includes explanations, exercises, and a comparison of the advantages and disadvantages of each method.
Typology: Study notes
1 / 6
This page cannot be seen from the preview
Don't miss anything!




class Node { public: Node(char v, Node* l, Node* r) : value(v), left(l), right(r) {} char value; Node* left; Node* right; };
Node *a = new Node(’a’, NULL, NULL); Node *b = new Node(’b’, NULL, NULL); Node *c = new Node(’c’, a, b); a = NULL; b = NULL; c->left = c; c = NULL;
24.4 Memory Model Exercise
address 100 101 102 103 104 105 106 107 value a b c d e f g h left 0 0 100 100 0 102 105 104 right 0 100 103 0 105 106 0 0
root: 105
24.5 Garbage Collection Technique #2: Stop and Copy
(a) Place scan and free pointers at the start of the copy memory. (b) Copy the root to copy memory, incrementing free. Whenever a node is copied from working memory, leave a forwarding address to its new location in copy memory in the left address slot of its old location. (c) Starting at the scan pointer, recursively copy the left and right pointers. Look for their locations in working memory. If the node has already been copied (i.e., it has a forwarding address), update the reference. Otherwise, copy the location (as before) and update the reference. (d) Repeat until scan == free. (e) Swap the roles of the working and copy memory.
24.6 Stop and Copy Exercise
Perform stop-and-copy on the following with root = 105:
WORKING MEMORY address 100 101 102 103 104 105 106 107 value a b c d e f g h left 0 0 100 100 0 102 105 104 right 0 100 103 0 105 106 0 0
address 108 109 110 111 112 113 114 115 value left right
root: 105 scan: free:
#include
// ============================================================================== class Node { public: Node() { value=’?’; left=-1; right=-1; } // initialized with "garbage" values char value; Address left; Address right; };
// ============================================================================== class Memory { public: Memory() { root = MY_NULL; }
// Return the node corresponding to a particular address Node& operator[](Address addr); // allocate a new node virtual Address my_new(char value, Address l, Address r) = 0; // print the contents of memory friend ostream& operator<<(ostream &ostr, Memory &m); virtual void print_availability(ostream &ostr) = 0;
// the user must set this value such that all useful memory is // reachable starting from root (NOTE: publicly accessible) Address root; protected: Node memory[CAPACITY]; // total machine memory };
// ============================================================================== class CPP_Memory : public Memory { public: CPP_Memory() { for (int i=0; i < CAPACITY; i++) available[i] = true; next = 0; } Address my_new(char v, Address l, Address r); void my_delete(Address addr); // explicit memory management void print_availability(ostream &ostr); protected: bool available[CAPACITY]; // which cells have been allocated int next; // where to start looking for the next available node };
// ============================================================================== class StopAndCopy_Memory : public Memory { public: StopAndCopy_Memory() { partition_offset = 0; next = 0; } Address my_new(char v, Address l, Address r); void collect_garbage(); // automatic memory management void print_availability(ostream &ostr); protected: void copy_help(Address &old_address); int partition_offset; // which half of the memory is active int next; // next available node };
#include <assert.h> #include "memory.h"
// ============================================================================== Node& Memory::operator[](Address addr) { // Return the node corresponding to a particular address if (addr == MY_NULL) { std::cerr << "ERROR: NULL POINTER EXCEPTION!" << endl; exit(1); } if (addr < OFFSET || addr >= OFFSET+CAPACITY) { cerr << "ERROR: SEGMENTATION FAULT!" << endl; exit(1); } return memory[addr-OFFSET]; }
ostream& operator<<(ostream &ostr, Memory &m) { ostr << "root-> " << m.root << endl; for (int i = 0; i < CAPACITY; i++) { ostr.width(4); ostr << i+OFFSET << " "; } ostr << endl; for (int i = 0; i < CAPACITY; i++) { ostr << " "; ostr.width(1); ostr << m.memory[i].value << " "; } ostr << endl; for (int i = 0; i < CAPACITY; i++) { ostr.width(4); ostr << m.memory[i].left << " "; } ostr << endl; for (int i = 0; i < CAPACITY; i++) { ostr.width(4); ostr << m.memory[i].right << " "; } ostr << endl; m.print_availability(ostr); return ostr; }
// ============================================================================== Address CPP_Memory::my_new(char v, Address l, Address r) { // starting at next, walk through the memory to find the first // available address. If we walk in a circle, we’re out of memory. for (int i=0; i < CAPACITY; i++, next++) { next %= CAPACITY; if (available[next] == true) { available[next] = false; memory[next].value = v; memory[next].left = l; memory[next].right = r; return OFFSET + next++; } } cerr << "ERROR: OUT OF MEMORY!" << endl; exit(1); }
void CPP_Memory::my_delete(Address addr) { // makes a node available for re-use if (addr == MY_NULL) return; // deleting a NULL pointer is not an error in C++ if (addr < OFFSET || addr >= OFFSET+CAPACITY) { cerr << "ERROR: SEGMENTATION FAULT!" << endl; exit(1); } if (available[addr-OFFSET] == true) { cerr << "ERROR: CANNOT DELETE MEMORY THAT IS NOT ALLOCATED!" << endl; exit(1); } available[addr-OFFSET] = true; }
void CPP_Memory::print_availability(ostream &ostr) { // print "FREE" or "used" for each node for (int i = 0; i < CAPACITY; i++) { (available[i])? ostr << "FREE " : ostr << "used "; } ostr << endl; }