Most Common Memory/Resource Leak Errors

2019-05-02 15:44发布

问题:

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.

回答1:

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.


回答2:

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.



回答3:

  • 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.


回答4:

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();


回答5:

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)