views:

312

answers:

5

All good C++ programmers know how to avoid leaking memory (or resources like sockets):

  1. Always use smart pointers, i. e.: std::auto_ptr, boost::shared_ptr.
  2. Always be aware of ownership of object: who owns, who refers, who is responsible, etc.

But, memory leaks still happen. Point most common issues when you discovered a memory leak in a program, even when you used the above techniques.

I start:

Sometimes you forget to define a destructor of base class as virtual. So all derived classes referred by pointer to the base class which was not destroyed properly and therefore leaked.

+2  A: 

Circular references are common, and they aren't solved by std::auto_ptr or boost::shared_ptr There is no substitute for (2) on your list, which is using your brain.

Justicle
Unfortunately. But *never* use your brain for something that a computer can do perfectly well for you ;-)
Steve Jessop
+3  A: 

There are many more types of errors than just leaks. In order from worst to best:

Memory corruption.

Data is stored to an area where it shouldn't. This results in both the majority of security problems and is by far the hardest to track down.

  • "Random location" corruption
    • Data is stored to a memory location that the user can control.
    • Data is stored to an array without checking the indices.
    • An object of a type derived from X is stored to an array element reserved for a base type of X, and the size of X is greater than the size of its base.
  • Lifetime corruption
    • Data is store to a memory location after it is freed.
    • Incorrect method of freeing is used (mismatch resulting in new/free, malloc/delete)
    • delete or free is called twice on the same pointer.

Failure to release memory

Memory no longer in use by the program remains allocated.

  • Incorrect method of freeing is used: mismatch resulting in new[]/delete instead of new[]/delete[].
  • Memory is not automatically release because of a circular reference in a reference counting scheme, such as can happen when smart_ptr is used in a circular data structure without attention to using weak_ptr for the circular link.
  • Memory is not freed due to a lost pointer - the last pointer to the memory was cleared before free was called, so there is no way to release it.
  • Memory is not freed due to not properly identifying when the data it contains is no longer needed. An example is a static cache used for some temporary task is never cleared out.
280Z28
+2  A: 
  • Calling a virtual function like "cleanup" from within the base-class destructor. You probably only do this once... (no more polymorphism in the destructor of the base-class)
  • Not cleaning up an stl::multimap (no erasing, only inserting) and wondering why your program keeps on becoming slower.
stefaanv
A: 

A mistake made by people too familiar with automatic garbage collection (through smartpointers):

class A { 
public:
    int avery_useful_calculation()const { return 4; } 
private:
    // class shouldn't be instantiated as an automatic variable (on stack)
    virtual ~A(){} 
};

// client code: needs a very useful calculation

int i = (new A)->avery_useful_calculation();
xtofl
Good example of a leak... but maybe change the comment next to the private virtual constructor to say something like "class can't be instantiated **on the stack**" or something like that?
Dan
A: 

Maybe I am out of scope, but I had some strange errors trying to "delete" uninitialized pointers.

To "avoid" memory leakage, I use the try {} __finally {} structure if implemented (but I read somewhere it may be inefficient if an exception was raised in a sub-sub-call)

first of all, there is no such thing finally in `C++`, it is just microsoft ext.. You should use `std::auto_ptr` that destroyes to object when you exit scope. Actually, C++ does not need finally because it has deterministic destructors.
Artyom
Thank for the information... I precised "if implemented" because it is not standard but may be usefull. By the way, I use it in Borland where there is a similar ext.