Heap tracing, bug hunting, and smart pointers — ~30–35 min
For each snippet, fill in the state of the heap and stack pointers after each line executes.
1int* p = new int(10); 2int* q = p; 3*q = 20; 4delete p;
| After line | Heap | Stack pointers |
|---|---|---|
| Line 1 | ||
| Line 2 | ||
| Line 3 | ||
| Line 4 |
1int* a = new int(5); 2int* b = new int(10); 3*a = *b + 3; 4delete b; 5b = nullptr;
| After line | Heap | Stack pointers |
|---|---|---|
| Line 1 | ||
| Line 2 | ||
| Line 3 | ||
| Line 4 | ||
| Line 5 |
1int* arr = new int[3]; 2arr[0] = 10; arr[1] = 20; arr[2] = 30; 3int* p = arr + 1; 4cout << *p; // prints 20 5delete[] arr;
| After line | Heap | Stack pointers |
|---|---|---|
| Line 1 | ||
| Line 2 | ||
| Line 3 | ||
| Line 5 |
1int** pp = new int*(new int(42)); 2cout << **pp; // prints 42 3delete *pp; 4delete pp;
| After line | Heap | Stack pointers |
|---|---|---|
| Line 1 | ||
| Line 3 | ||
| Line 4 |
Each snippet has a memory bug. Identify the bug type from the dropdown, then write the corrected code.
void process(int n) { int* data = new int[n]; if (n <= 0) return; // ... use data ... delete[] data; }
return exits before delete[] runs. What happens to the allocated memory?int* createValue() { int val = 42; return &val; } int* p = createValue(); cout << *p;
val is a local variable on the stack. What happens to it when the function returns?int* a = new int(10); int* b = a; delete a; delete b; // boom!
a and b point to the same address. What happens when you delete both?int* arr = new int[100]; // ... fill array ... delete arr; // wrong!
new[] but freed with delete (no brackets). What should it be?Fill in the three missing methods. The class manages a heap-allocated array that grows when full.
push_back.
class DynArray { int* data; int size; int capacity; public: DynArray(int cap); // Task 1 ~DynArray(); // Task 2 void push_back(int val); // Task 3 int get(int index) { return data[index]; } };
Implement DynArray(int cap): allocate data on the heap, initialize size and capacity.
new int[cap] to allocate, set size = 0, and capacity = cap.Implement ~DynArray(): free the heap memory.
data was allocated with new[], so you need delete[].Implement push_back(int val): if the array is full, double the capacity (allocate new array, copy elements, delete old). Then append val.
capacity *= 2, (2) int* newData = new int[capacity],
(3) loop to copy old elements, (4) delete[] data, (5) data = newData.
Then always: data[size++] = val.
Convert each snippet from raw pointers to smart pointers. Remove manual delete.
Original:
void process() { int* p = new int(42); cout << *p; delete p; }
Rewrite using unique_ptr:
auto p = make_unique<int>(42); — no delete needed.Original:
Widget* w = new Widget(); componentA->use(w); componentB->use(w); // who deletes? delete w;
Rewrite using shared_ptr:
auto w = make_shared<Widget>(); — pass w to both components. No delete needed; last owner frees it.