SEARCH THIS BLOG

MEMORY LEAK


What actually happens when we delete a pointer ?

A pointer is like any other variable when it comes to taking space in the memory. But instead of storing any values, it stores the memory address of the block it is pointing to. We know that by using delete we can free the dynamically allocated memory. But the point to keep in mind is that the pointer itself is not dynamically created. It just holds the address of a dynamically created memory block. This means that the pointer cannot be deleted using delete keyword, but the memory it’s pointing to can be deleted.

Look at the following code and then see the explanations :

#include<iostream>

using namespace std;

int main()

{

int * iptr;                    // statement 1   

iptr = new int(25);   // statement 2

delete iptr;                 // statement 3

iptr = new int(12);   // statement 4

return 0;

}

Statement 1 creates an integer pointer iptr. This means the compiler provides a space of 8 bytes to iptr somewhere in the memory. As it is not initialized, iptr, at present, doesn’t hold any address.

Statement 2 is the dynamic allocation statement (allocation using new). It creates a 4 bytes space in memory somewhere, stores the value 25 in it and then returns its address to iptr.

Statement 3 uses the deallocation operator delete. This does not delete the pointer iptr, as it may seem from the code. The delete operator can only deallocate the memory created through new. By using the pointer, we simply specify the address to be deleted. So, after delete, iptr is still present in the memory till its scope is over. This is shown in statement 4 where we use the pointer again to create another memory block using new.

Also, when we delete a memory block, we are not talking of actually deleting the value stored in that block. The block is passed back to operating system for reuse, may be with the value still stored in it as a garbage value or clearing it. C++ does not make any guarantees about what will happen to the contents of deallocated memory. All we know is further dynamic creations of memory using new can utilize the deleted memory.

 

Dangling Pointers

C++ gives no clue as to what value is stored in the pointer after a delete statement. In most cases, the memory returned to the operating system will contain the same values it had before it was returned, and the pointer will be left pointing to the now deallocated memory.

A pointer that is pointing to a deallocated memory is called dangling pointer. Dereferencing or deleting a dangling pointer will lead to undefined behaviour.

Consider the following program :

In the above program, the value of 7 that was previously assigned to the allocated memory will probably still be there, but it’s possible that value at that memory address could have changed. It’s also possible the memory could be allocated to another application (or for the operating system’s own usage), and trying to access that memory will cause the operating system to shut the program down.

Few precautions that will avoid dangling pointer errors

First, try to avoid having multiple pointers point to the same memory location. If this is not possible, always be clear about all the pointers accessing the same memory address.

Second, when you delete a pointer, if that pointer is not going out of its scope immediately afterward, set its value as NULL or nullptr.

 

Memory Leaks

There is no doubt about the fact that new and delete are very useful. But they have an associated problem that it is easy to forget to delete something that was previously allocated with new, leaving an orphaned memory block – a block that is still allocated but which has nothing referencing it. This means that a memory block which was created is still in use but there’s no way to access it.

Here are the many reasons that might lead to memory leak :


Forgetting to delete something that has been dynamically allocated (using new).

There can be a number of instances where you might forget to delete a memory allocated through new. One such very common example is not deleting a dynamic memory created within a function. Look at the following code :

 

void fun ()

{

       int * iptr = new int;

       /*  full function body */

}

 

In the above function, the memory allocated through new is never freed. Every time this function is called, a new memory is created which is later not deleted. These dynamically allocated memories have a dynamic scope and remain in memory for the entire program run. As a result, there is a continuous memory leak each time the function is called.


Failing to notice that code may bypass a delete statement under certain circumstances :

 

Consider the code below :

 

void fun()

{

   int n; cin>>n;

   int * iptr = new int;

   * iptr = n;

   if (* iptr < 6)

        cout << “Less than 6” ;

   else

        delete iptr;

}

 

The above code is absolutely fine when it comes to syntax. Thus, the compiler shows no error. But if the user inputs a number less than 6, the control never actually passes to the delete statement. So, every time the function is called and the user inputs a number less than 6, memory is lost.


Assigning a new address to a pointer which was already pointing to an allocated object.

 

See the code below :

 

int main()

{

     int a = 5;

     int * iptr = new int;

     iptr = &a;

     return 0;

}

 

Here, a is a static variable which has a certain address. A new memory is dynamically allocated which is being pointed to by the pointer iptr. Now when the address of a is assigned to iptr, the address of the dynamically allocated memory is lost. There is no way to access that memory block. Thus, it results in a memory leak.

 

What is the actual meaning of memory leak ?

 Every program at the time of compilation is sent to the compiler. The compiler reads the program and if it finds no errors it feeds the program to the main memory. Every program is given a certain amount of memory. This is the memory a program can use in its entire run. This memory includes spaces for global variables, local variables and functions; as well as the heap memory for dynamic allocations.

Whenever a new memory block is created using new, a part of this heap is used. As heap is not infinite, it may happen that all the heap is used up and there is no space left for creation of a new memory block. To reduce this risk, it is important to avoid memory leaks. It is very important to free the memory that is no longer needed so that it may be used again by the program.

Whenever a memory address is leaked, the operating system still considers that memory block to be useful to the program. But once the memory is leaked, we have no way to get back its address in order to modify or delete it. So, that particular memory block becomes completely useless for rest of the program. This memory block remains in the memory until the program completely terminates.

 

 



Which topics you want an article on? Comment down on this post.

Do not stop here. Read all articles related to C++ here.

If you want to contribute any article for the website, feel free to share it on coding.nkcoder@gmail.com. We will publish it on the website with your name.

Download the pdf form of this article here.

Related Topics :

Introduction to pointers

Static & Dynamic memory allocation

Declaration and Initialization of pointers

Pointer Arithmetic

Dynamic Allocation Operators

Pointers & Constants

 

 

 


Post a Comment