Jul 052012
 

Those who use languages like C and C++ that support user defined pointer variables, put utmost emphasis on implementing the pointers correctly. And rightfully so, A pointer wrongly handled can be catastrophic. And that’s an understatement 🙂 .

Lets consider the below code which read and print n numbers using pointers:

    // Memory leaks...
    int *ptr;
    for(int i=0; i<n; i++){
        ptr = (int*) malloc(sizeof(int));
        scanf("%d", ptr);
        printf(" You entered : %d", *ptr);
    }

The code is written in C, but an equivalent code can be written in C++ using new, delete, cin & cout. I can hear you shouting “Bad code”. I promise to use it as a bad example only.

Lets consider the problems in above code :

line-1: ptr is a dangling pointer, C language don’t initialize the auto variables with a default value. Though it will not create any problem in the above code because its most simplistic code. But if you develop a habit of not initializing pointers, and keep writing codes like above, then a day will code when some else, if not you, will come and write a code between line-1 & line-2 and may try to dereference it.

line-4: we don’t check for ptr being null (or if an exception has occurred during the memory allocation). What if compiler does not have enough memory to allocate, it will either return a null pointer (C) or will trow an exception (C++), but we didn’t put a check for either.

line-6: we didn’t free the memory allocated to ptr. That’s like breaking the most important & obvious rule of the game. You must return the heap memory before the last pointer pointing to the memory goes out of focus (and ideally as-soon-as you think you don’t need it.

My friend says that “people are not difficult, they are different!”, I say the same for pointers. while dealing with pointers, you only need to take care of the two problems, Dangling pointers and Memory leaks.

1. Dangling pointers:

A dangling pointer is a pointer which points to an invalid object. We can have dangling pointers because of multiple reasons:

An un-initialized, non-static local pointer variable is a dangling pointer. auto variables are not initialized in C & C++. the value they contain is garbage. For example in the above code

    int * ptr;

ptr is a dangling pointer. Sometimes, such dangling pointers are also called wild pointers. Some languages (like java) gives compile time error if you try to use a variable which is not explicitly initialized.

Note that the below is not a dangling pointer because static variables are initialized to zero (NULL)

    static int * ptr; // Not a dangling pointer

destroying the stack frame (the variable which the pointer points to goes out of scope)

    int *ptr = NULL;
    {
        int temp = 10;
        ptr = &temp
    } // temp goes out of scope and ptr becomes dangling after this point

explicitly deleting the memory, which the pointer points to

    int * ptr = new int;
    delete ptr; // ptr is dangling pointer now.
    ptr = NULL; // best practice to always assign NULL after deleting a pointer.

Sometimes, this is done indirectly, as shown below,

    int * ptr = new int;
    int *new_ptr = ptr
    delete ptr;
    ptr = NULL;  // Ok

In the above code ptr is not a dangling pointer but since new_ptr also points to the same memory location, new_ptr becomes a dangling pointer. (Because the memory location to which it points is deallocated).

Returning address of a local variable on stack.

    int * function func()
    {
        int abc;
        return &abc; // returning address of a local variable
    }

The stack-frame (activation record) of the function, on which abc resides will be deallocated when the function returns. So the address returned from the function does not points to the allocated memory.

2. Memory leaks:

A memory leak is a situation when there exist a memory, which is allocated to the program but cannot be accessed. Such memory develops on heap, when a user allocate the memory but change the pointer which hold the address to that location. Below are few example of how a developer manufactures them:

Reassign a pointer before deleting what the pointer was originally pointing to. One example of this is seen in the for loop of our main example, another example is shown below:

    // Memory allocated on heap and address stored in ptr
    int * ptr = new int;

    // the previous memory is now a memory leak
    ptr = new int;

Not deleting the pointer before it goes out of focus. (This may look as another variation of the above).

    void func()
    {
        int * ptr = new int;

        // do some work..
    }

the memory allocated to ptr will be a leak.

This problem is actually more complex than it looks. Suppose you write the below ‘good code’

    void func()
    {
        int * ptr = new int;

        // do some work..
        delete ptr;
    }

But then an exception occurs in the code before the delete command. Since you do nothing to handle the exception, that exception will be propagated to the calling function. Even if the calling function handles the exception gracefully, there will be a leak in the above function.

A solution to this may be to put the entire code in try catch and then delete the pointer in the catch part as well.

    void func()
    {
        int * ptr = new int;

        try{
            // do some work..
        } 
        catch (…) // … means catch all exceptions
        { 
            delete ptr; // avoid memory leak when an exception is thrown
            throw; // propagate exception to caller
        }
        delete ptr;
    }

The above code solves the problem of memory leak, though at the cost of making the code less readable. C++ has a concept of smart pointers which come to rescue in above situations where you want to avoid memory leak and don’t want to clutter your code. I reserve the discussion of smart pointer and auto_ptr for some later post.

  5 Responses to “Memory leaks and dangling pointers”

Comments (5)
  1. “They are scum, they want to take over the world economies and control earth as we know it. This leaves a difference in price between the Kindle 3G and Kindle Wireless reading device of $50. Run Firefox; Microsofts Internet Explorer is clunky and the most hacked software on the planet.

  2. In Vista the process is similar and your goal is “Service Pack 1″.
    Even with that, I’ve noticed extremely poor charge times, nothing like the OEM home or car chargers.

    And a”new version of Windows Backup will provide a more capable system than any prior version”of such under any
    name it has taken during its”existence as part of
    Windows has”ever had.

  3. This means being there even when it isn’t easy or convenient and
    when they aren’t interested in having you around. The crates purpose is not for punishment or
    shutting away the puppy from you and your family.
    For this task, you need to stay prepared with lots of patience as well as
    understanding.

  4. No exception is throw. the code will behave in an undefined way and may also crash or corrupt another variables

  5. which exception is thrown if dangling ptr address is accessed

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)