We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← RAII: Objects With Lifetimes step 3 of 4
The delete you will forget
Buffer* b = new Buffer(size);
use(b);
delete b;
Three lines, and the middle one can ruin the third. If use throws, the
delete never runs. If someone later adds an early return between them, the
delete never runs. If someone adds a second exit path and remembers the
delete on one but not the other, it runs sometimes.
This is the most common memory leak in C++ and it is never written by someone who forgot that memory must be freed. It is written by someone who freed it in one place, and then the function grew a second exit.
The rule
In modern C++,
newanddeleteshould not appear in ordinary code.
Not “use them carefully” — do not write them. They belong inside the implementation of a container or a smart pointer, written once, by someone who is thinking about nothing else at the time.
What replaces them:
| Instead of | Write |
|---|---|
new T(...) then delete |
a local T — the stack is free |
new T[n] then delete[] |
std::vector<T> |
new T you must return |
std::make_unique<T>(...) |
| shared ownership |
std::make_shared<T>(...) — and read Track 4 first |
The first row is the one people skip past, and it is the most important. Most heap allocations in C++ code exist for no reason. A local object is allocated by moving a stack pointer, freed by moving it back, and destroyed automatically at the end of the block. If the object does not need to outlive the scope, the scope should own it.
Why [] matters, and why you will not miss it
new T[n] must be freed with delete[], not delete. Getting that wrong is
undefined behaviour rather than an error. You will not be diagnosed and the
program will usually appear to work.
This is a rule you never have to remember once you stop writing new, which
is the point.
A note on how this one is graded
A leak normally shows up as nothing at all: the answer is right, the tests pass, and the memory is gone. That is exactly why leaks survive review, so this problem makes the leak visible. The bucket type counts how many of itself are alive, and the harness reports that number after your function has returned.
So each test checks two things: the histogram, and a live-object count that must be back to zero. A run that returns the right answer and leaves objects alive fails — which is the judgement a real code reviewer would make and a normal test suite would not.
Your task
std::vector<int> histogram(const std::vector<int>& values, int buckets);
Count how many of values fall in each bucket. Bucket i covers values v
where v % buckets == i. Negative values are ignored, and any value above
1,000,000 abandons the whole histogram and returns empty. buckets of zero
or less returns an empty vector.
The starter allocates the buckets with new[] and frees them on one of its
three exits. Rewrite it so that no new or delete appears anywhere, and
the leak stops being possible rather than being fixed.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.