Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different ways of leaking memory

The basic concept of memory leaking is a mismatch of a new/delete operation during code execution, either due to wrong coding practices or either in cases of errors when the delete operation is skipped.

But recently I was asked a question in an interview about other ways in which memory can leak. I had no answer to it. What is it?

like image 629
ashishsony Avatar asked Jul 03 '11 05:07

ashishsony


2 Answers

Common dynamic memory problems are:

  • Dynamic memory allocation with new and not deallocating with delete.
  • Dynamic memory allocation with new[] and deallocating with delete.
  • Dynamic memory allocation new and deallocate it with free.
  • Dynamic memory allocation malloc and deallocate it with delete.

In addition to memory leaks/memory corruption the last 3 scenarios will cause the dreaded Undefined Behavior.

A few other potential memory leak causing scenarios that I can recollect are:

  • If a pointer, pointing to a dynamically allocated memory region is re-assigned a new value before being deallocated, it will lead to a dangling pointer and a memory leak.

A code example:

char *a = new[128];
    char *b = new[128];
    b = a;
    delete[]a;
    delete[]b; // will not deallocate the pointer to the original allocated memory.

- Pointers in STL Containers

A more common and often encountered scenario is, Storing pointers pointing to dynamically allocated types in STL containers. It is important to note that STL containers take ownership of deleting the contained object only if it is not a pointer type.
One has to explicitly iterate through the container and delete each contained type before deleting the container itself. Not doing so causes a memory leak.
Here is an example of such an scenario.

- The Non virtual Base class destructor problem

Deleting an pointer to Base class which points to any dynamically allocated object of derived class on heap. This results in an Undefined Behavior.

An code example:

class MyClass
{
    public:
    virtual void doSomething(){}
}; 
class MyClass2 : public MyClass 
{ 
    private:  
        std::string str;  
    public: MyClass2( std::string& s) 
    {  
        str=s; 
    }  
    virtual void doSomething(){}
};  

int main()
{  
     std::str hello("hello"); 
     MyClass * p = new MyClass2(hello);  
     if( p ) 
     { 
        delete p;  
     } 
     return 0;
}

In the example only the destructor MyClass::~MyClass() gets called and MyClass2::~MyClass2() never gets called. For appropriate deallocation one would need,

MyClass::virtual ~MyClass(){}

- Calling delete on a void pointer

A code example:

void doSomething( void * p ) 
{
    //do something interesting
    if(p)
       delete p; 
}

int main()
{
    A* p = new A();
    doSomething(p);
    return 0;
}

Calling delete on a void pointer as in above example, will cause a memory leak and a Undefined Behavior.

like image 136
Alok Save Avatar answered Oct 06 '22 19:10

Alok Save


As an interview question, the interviewer may have been looking for broader perspective than the textbook new/delete mismatch.

Any memory that persists beyond the last point that it is needed can be considered "leaked". This memory may eventually be freed manually with a delete further down in the code, making these leaks temporary rather than the permanent leaks you encounter with mismatched new/delete operators. For the duration of time that the "leak" persists though, the net effect is the same. You are reducing the amount of available resources (memory) to other parts of your program.

In garbage-collected code, memory is considered leaked if you continue holding any references to an object that you no longer need, thus preventing the garbage collector from reclaiming it. If you hold onto unneeded objects indefinitely, you've created a permanent leak in garbage-collected code.

like image 39
Justin Aquadro Avatar answered Oct 06 '22 19:10

Justin Aquadro