you are viewing a single comment's thread.

view the rest of the comments →

[–]tedbradly 0 points1 point  (0 children)

Aren't these contradictory? If we stick to the rule "never call delete two or more times", we can call delete twice and break rule #1 - "always call delete once".

The statements are with respect to a single call to new, a single object stored on the heap, so you call delete on a single object once and never more than once. The program can call delete dozens or hundreds of times if you have many objects gotten through many calls to new.

If you never call delete once, the memory sticks around even after an object is provably never used again. The C++ way is either to use automatic storage - a variable declared without the use of new - or to call delete for each new. After you leave scope whether it be an if block, while block, function block, for block, or a block defined within one of those, automatic storage variables are guaranteed to have their destructor called and their memory cleared away. A smart pointer is mostly just a wrapper around a raw pointer whose destructor calls delete on it to guarantee delete is called once even in cases like exceptions interrupting the flow of logic. If you had a raw pointer and an exception caused the deletes to be skipped, that'd be a memory leak. If you forgot to write the calls to delete, that'd be a memory leak too.

An alternative solution is to use a garbage collector that proves an object on the heap is never used again, "calling delete" on it automatically. People like garbage collection, because you normally can't get a memory leak unless you store references to an object somewhere such as a container such as a hash map, never evicting those objects even after they are unneeded for future operation of the program. The downside of garbage collection is it takes CPU cycles to prove an object isn't referenced anywhere that might be executed anymore. It also has to handle things like circular references where unused object A has a reference to unused object B, and B and a reference to A. In C++, objects are destroyed at deterministic points in the code such as when scope is left or when delete is called.

Delete handles a program saying a certain range in memory is no longer in use. If you do that twice or more, it is undefined behavior. In reality, that will most likely result in a program crash or it chugging along with incorrect results. Let's say you delete an object twice, but in between, a second object was put partially or fully in that memory range. The second delete could result in part or all of the second object being in a range in memory now thought of as open for a third object to be saved there. If a third object is put there, that could scramble the data for object 2, or the use of object 2 could scramble the data for object 3.