16

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ashishsony
  • 2,537
  • 3
  • 26
  • 38

7 Answers7

18

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.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 1st point and last point are same. They are just different scenarios. – iammilind Jul 03 '11 at 05:55
  • Not using exception safe code (derivation from 'improper' destruction in unwinding). http://www.civilnet.cn/book/kernel/Effective%20C++%20(Third%20Edition)/ch05lev1sec4.html – Hernán Jul 03 '11 at 05:59
  • 3
    @iammilind: Well everything boils down to the same point and the only point, rest are all scenarios. – Alok Save Jul 03 '11 at 05:59
  • in the dangling pointer example, delete[] a; and delete[] b; is in itself a disaster as deleting already deleted pointer can prove fatal?is it? – ashishsony Jul 03 '11 at 06:52
  • 3
    Don't forget just keeping objects around that will never be used again. This is the classic "caching" memory leak where a cache of objects grows forever. It's that one that garbage collection also can't help with. – edA-qa mort-ora-y Jul 03 '11 at 07:00
  • I disagree. The first bullet point is a common memory leak, yes, but the other 3 **while they are certainly errors** they don't introduce memory leaks on windows and linux which are the most used platforms ever. So they are anything but common reasons for memory leaks. – Andreas Bonini Jul 03 '11 at 13:12
  • @Andreas: perhaps you'd care to qualify "they don't introduce memory leaks on windows and linux" with your choice and version of compiler, and...? – Tony Delroy Jul 04 '11 at 01:33
  • @Tony: gcc and msvc, the two most common ones – Andreas Bonini Jul 04 '11 at 07:02
  • @Andreas Bonini: While I cannot claim a 100% that the 3 scenarios produce memory leaks, They still are Undefined Behaviors, How can you so convincingly define a Undefined Behavior? – Alok Save Jul 04 '11 at 07:50
  • @Als: well you can just try and see :) If you say that they are common *errors* then I have no objections, again I agree that it shouldn't be done. But they aren't common memory leaks – Andreas Bonini Jul 04 '11 at 08:02
4

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.

Justin Aquadro
  • 2,280
  • 3
  • 21
  • 31
  • as far as i know java works with references.. so is there a way in java to hold references to objects even after they go out of scope.. so then the referent should be available for garbage collection isn't it? – ashishsony Jul 03 '11 at 06:38
  • In your main method, in static fields, for a couple examples of references that will persist until the end of execution if you let them. – Justin Aquadro Jul 03 '11 at 06:41
  • In Java, the common mistake is to forget about a reference to an object, usually in connection with listeners. Say, window1 is listening to window2, you remove window1 from your gui, but because window2 still contains a reference to it in its list of listeners, it will not be gc-ed. One way around this is to use WeakReference. – Jirka Jul 03 '11 at 09:44
3
  1. Allocating memory with new/new[]/malloc and not freeing it
  2. Allocating memory to some pointer and overwrite it accidently e.g. p = new int; p = new int[1];
  3. Allocating memory in air. i.e. new int[100]; or cout<<(*new string("hello"))<<endl;
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Believe me, I have fixed memory leak which was like point 3 (it was custom memory allocator function rather than `new`). – iammilind Jul 03 '11 at 05:41
2

There's always my favorite, the "non-leaking memory leak", where your program correctly retains pointers to the allocated memory, but (for whatever reason) never actually gets around to freeing the memory they point to:

// Maybe not technically a memory leak, but it might as well be one
static vector<const char *> strings;

void StoreTheString(const char * str)
{
   strings.push_back(strdup(str));
}

It's doubly annoying because memory-leak-detector programs won't recognize it as a memory leak (because the pointers are still reachable), and yet your program will nonetheless eat up memory until it crashes.

This sort of problem can occur even in garbage-collected languages like Java.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • i think this is what @Als pointed out about stl containers.. that if they are feeded pointers.. they dont delete the concrete object when go out of scope as they dont take up their ownership? – ashishsony Jul 03 '11 at 06:29
2

Another scenario is when using reference-counting smart pointers, like boost::shared_ptr, which are commonly thought to "eliminate memory leaks" but you create cyclical references.

How to avoid memory leak with shared_ptr?

Community
  • 1
  • 1
e.dan
  • 7,275
  • 1
  • 26
  • 29
1

Fragmentation could be one of the problems that cause Out of Memory. After a pro-longed running of your programs, it may cause memory fragmentation.

TheOneTeam
  • 25,806
  • 45
  • 116
  • 158
0

I use the Boehm garbage collector with overloaded operator new and delete, and which works perfectly for any class that was compiled with it, but fails horribly with std::string and a few STL containers as well, even if the variables are members of a garbage collected class. Had a few memory leaks until I realized it. Thankfully it provides a garbage collected allocator.

Also I remember a self-driving car that was programmed in Java, but crashed* every 20 to 40 minutes. It collected object detection information about various bits of undergrowth and trash it encountered along the road, subscribed them to some queue, ...and never removed them.

*: See what I did there :D

Frigo
  • 1,709
  • 1
  • 14
  • 32