Does this produce a memory leak? - c++

I'm following a book on C++ programming, and I'm following the exercises. One exercise asks me to create a program that produces a memory leak. Will this program produce such a leak?
int main()
{
int * pInt = new int;
*pInt = 20;
pInt = new int;
*pInt =50;
return 0;
}

Considering it is a trivial example, not having a delete paired with your new is a leak. In order to prevent a leak in this case you would need the following:
int * pInt = new int;
*pInt = 20;
delete pInt ;
pInt = new int;
*pInt =50;
delete pInt ;
A decent tool to use to detect memory leaks is Valgrind. I ran the tool on your sample code, like so:
valgrind ./a.out
and this is part of the output it produced:
==14153== HEAP SUMMARY:
==14153== in use at exit: 8 bytes in 2 blocks
==14153== total heap usage: 2 allocs, 0 frees, 8 bytes allocated
==14153==
==14153== LEAK SUMMARY:
==14153== definitely lost: 8 bytes in 2 blocks
Which confirms that indeed the program does leak memory.

Yes. To avoid leaks, every time you call new, you have to have a matching call to delete. You have 2 calls to new and no calls to delete, so you have 2 leaks.
Note that when your program exits, the OS will free up all the memory you've allocated with new. So memory leaks are really only a problem for non-trivial programs.

One exercise asks me to create a program that produces a memory leak.
Will this program produce such a leak?
an utter exercise , and your code is a better answer to exercise !
Pointers and memory leaks. These are truly the items that consume most of the debugging time for developers
Memory leak
Memory leaks can be really annoying. The following list describes some scenarios that result in memory leaks.
Reassignment, I'll use an example to explain reassignment.
char *memoryArea = malloc(10);
char *newArea = malloc(10);
This assigns values to the memory locations shown in Figure 4 below.
http://www.ibm.com/developerworks/aix/library/au-toughgame/fig4.gif
Figure 4. Memory locations
memoryArea and newArea have been allocated 10 bytes each and their respective contents are shown in Figure 4. If somebody executes the statement shown below (pointer reassignment )
memoryArea = newArea;
then it will surely take you into tough times in the later stages of this module development.
In the code statement above, the developer has assigned the memoryArea pointer to the newArea pointer. As a result, the memory location to which memoryArea was pointing to earlier becomes an orphan, as shown in Figure 5 below. It cannot be freed, as there is no reference to this location. This will result in a memory leak of 10 bytes.
http://www.ibm.com/developerworks/aix/library/au-toughgame/fig5.gif
Figure 5. Memory leak
Before assigning the pointers, make sure memory locations are not becoming orphaned.
Freeing the parent block first
Suppose there is a pointer memoryArea pointing to a memory location of 10 bytes. The third byte of this memory location further points to some other dynamically allocated memory location of 10 bytes, as shown in Figure 6.
http://www.ibm.com/developerworks/aix/library/au-toughgame/fig6.gif
Figure 6. Dynamically allocated memory
free(memoryArea)
**If memoryArea is freed by making a call to free, then as a result the newArea pointer also will become invalid. The memory location to which newArea was pointing cannot be freed, as there is no pointer left pointing to that location. In other words, the memory location pointed by newArea becomes an orphan and results in memory leak.
Whenever freeing the structured element, which in turn contains the pointer to dynamically allocated memory location, first traverse to the child memory location (newArea in the example) and start freeing from there, traversing back to the parent node.
The correct implementation here will be:
free( memoryArea->newArea);
free(memoryArea);
Improper handling of return values
At time, some functions return the reference to dynamically allocated memory. It becomes the responsibility of the calling function to keep track of this memory location and handle it properly.**
char *func ( )
{
return malloc(20); // make sure to memset this location to ‘\0’…
}
void callingFunc ( )
{
func ( ); // Problem lies here
}
In the example above, the call to the func() function inside the callingFunc() function is not handling the return address of the memory location. As a result, the 20 byte block allocated by the func() function is lost and results in a memory leak.
Sharp Reference at :
http://www.ibm.com/developerworks/aix/library/au-toughgame/
Update:
your interest let me for an edit
Simple rules to avoid Memory Leaks in C
You are allocating memory for p and q:
p=new int [5];
/* ... */
q=new int;
But you are only freeing p using an invalid operator, since arrays should be deleted using delete[]. You should at some point free both p and q using:
delete[] p;
delete q;
Note that since you are making your pointers point to the other pointer's allocated buffer, you might have to check which delete operator corresponds to which new operation.
You should use delete[] on the buffer allocated with new[] and delete with the buffer allocated with new.
Rule 1: Always write “free” just after “malloc”
int *p = (int*) malloc ( sizeof(int) * n );
free (p);
Rule 2: Never, ever, work with the allocated pointer. Use a copy!
int *p_allocated = (int*) malloc ( sizeof(int) * n );
int *p_copy = p_allocated;
// do your stuff with p_copy, not with p_allocated!
// e.g.:
while (n--) { *p_copy++ = n; }
...
free (p_allocated);
Rule 3: Don’t be parsimonious. Use more memory.
Always start by allocating more memory than you need. After you finish debugging, go back and cut on memory use. If you need an array 1000 integers long, allocate 2000, and only after you make sure everything else is OK – only then go back and cut it down to 1000.
Rule 4: Always carry array length along with you
Wherever your array goes, there should go with it it’s length. A nice trick is to allocate an array sized n+1, and save n into it’s 0 place:
int *p_allocated = (int*) malloc ( sizeof(int) * (n+1) );
int *p_copy = p_allocated+1;
p_copy[-1] = n;
// do your stuff with p_copy, not with p_allocated!
free (p_allocated);
Rule 5: Be consistent. And save comments
The most important thing is to be consistent and to write down what you do. I am always amazed at how many programmers seem to think that comments are a waste of time. They are imperative. Without comments, you probably won’t remember what you did. Imagine returning to your code a year after you wrote it, and spending countless hour trying to recall what that index does. Better to spend a couple of seconds writing it down.
Also, if you are consistent, you will not fail often. Always use the same mechanism for passing arrays and pointers. Don’t change the way you do things lightly. If you decide to use my previous trick, use it everywhere, or you might find yourself referring back to a nonexistent place because you forgot what type of reference you chose.
Ref : http://mousomer.wordpress.com/2010/11/03/simple-rules-to-avoid-memory-leaks-in-c/

Yes, this produces not one, but two memory leaks: both allocated ints are leaked. Moreover, the first one is leaked irrecoverably: once you assign pInt a new int the second time, the first allocated item is gone forever.

Will this program produce suck a leak?
Yes, it will.

Yes and no. When pInt is overwritten with a new int pointer, you lose that memory that was previously allocated, however when the program returns, most modern operating systems will clean up this memory, as well as the memory lost by not deallocating pInt at the end.
So in essence, yes, something like this will result in two memory leaks.

It does, because you allocate space with the statement "new int", but do not use "delete" to free the space.

Related

Accessing freed pointers can cause data corruption if malloc() allocates memory in the same spot unless the freed pointer is set to NULL

This Question statement is came in picture due to statement made by user (Georg Schölly 116K Reputation) in his Question Should one really set pointers to `NULL` after freeing them?
if this Question statement is true
Then How data will corrupt I am not getting ?
Code
#include<iostream>
int main()
{
int count_1=1, count_2=11, i;
int *p=(int*)malloc(4*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=3;i++)
{
*(p+i)=count_1++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
std::cout<<"\n";
free(p);
p=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(p+i)=count_2++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
}
Output
0xb91a50
1 2 3 4
0xb91a50
11 12 13 14
Again it is allocating same memory location after freeing (0xb91a50), but it is working fine, isn't it ?
You do not reuse the old pointer in your code. After p=(int*)malloc(6*sizeof(int));, p point to a nice new allocated array and you can use it without any problem. The data corruption problem quoted by Georg would occur in code similar to that:
int *p=(int*)malloc(4*sizeof(int));
...
free(p);
// use a different pointer but will get same address because of previous free
int *pp=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(pp+i)=count_2++;
}
p[2] = 23; //erroneouly using the old pointer will corrupt the new array
for(i=0;i<=3;i++)
{
std::cout<<*(pp+i)<<" ";
}
Setting the pointer to NULL after you free a block of memory is a precaution with the following advantages:
it is a simple way to indicate that the block has been freed, or has not been allocated.
the pointer can be tested, thus preventing access attempts or erroneous calls to free the same block again. Note that free(p) with p a null pointer is OK, as well as delete p;.
it may help detect bugs: if the program tries to access the freed object, a crash is certain on most targets if the pointer has been set to NULL whereas if the pointer has not been cleared, modifying the freed object may succeed and result in corrupting the heap or another object that would happen to have been allocated at the same address.
Yet this is not a perfect solution:
the pointer may have been copied and these copies still point to the freed object.
In your example, you reuse the pointer immediately so setting it to NULL after the first call to free is not very useful. As a matter of fact, if you wrote p = NULL; the compiler would probably optimize this assignment out and not generate code for it.
Note also that using malloc() and free() in C++ code is frowned upon. You should use new and delete or vector templates.

What is the difference between memory leak, accessing freed memory and double free?

I'm trying to figure out what is the difference between those three kinds of problems associated with memory models.
If I want to simulate a memory leak scenario, I can create a pointer without calling corresponding delete method.
int main() {
// OK
int * p = new int;
delete p;
// Memory leak
int * q = new int;
// no delete
}
If I want to simulate a double free scenario, I can free a pointer twice and this part memory will be assigned twice later.
a = malloc(10); // 0xa04010
b = malloc(10); // 0xa04030
c = malloc(10); // 0xa04050
free(a);
free(b); // To bypass "double free or corruption (fasttop)" check
free(a); // Double Free !!
d = malloc(10); // 0xa04010
e = malloc(10); // 0xa04030
f = malloc(10); // 0xa04010 - Same as 'd' !
However, I don't know what is accessing freed memory. Can anybody give me an example of accessing freed memory?
Memory leaks are bad.
Double frees are worse.
Accessing freed memory is worser.
Memory leaks
This is not an error per se. A leaking program is stil valid. It may not be a problem. But this is still bad; with time, your program will reserve memory from the host and never release it. If the host's memory is full before the program completion, you run into troubles.
Double frees
Per the standard, this is undefined behaviour. In practice, this is almost always a call to std::abort() by the C++ runtime.
Accessing freed memory
Also undefined behaviour. But in some case, nothing bad will happen. You'll test your program, put it in production. And some day, for no apparent reason, it will break. And it will break hard: randomly. The best time to rework your résumé.
And here is how to access freed memory:
// dont do this at home
int* n = new int{};
delete n;
std::cout << *n << "\n"; // UNDEFINED BEHAVIOUR. DONT.
Your examples of a memory leak (allocating memory but freeing it) and double-free (passing a pointer to allocated memory to free / delete more than once) are correct.
Performing a double-free does not however mean that a section of memory will be returned more than once by malloc as your example indicates. What it does do is invoke undefined behavior, meaning the behavior of your program cannot be predicted going forward.
Accessing free'ed memory means freeing a pointer and then subsequently trying to use it:
int *a = malloc(10 * sizeof(int)); // allocate memory
free(a); // free memory
print("a[0]=%d\n", a[0]); // illegal: use after free
You are correct about making a memory leak and a double-free. Accessing freed memory happens when you dereference a pointer that has been freed:
int *ptr = malloc(sizeof(int));
*ptr = 123;
free(ptr);
int invalid = *ptr; // Accessing freed memory
Problems like this are notoriously hard to detect, because the program continues to work as expected for some time. If you expect to reuse the pointer variable at some later time, it is a good idea to assign it NULL immediately after calling free. This way a subsequent dereference would fail fast.
I'm trying to figure out what is the difference between those three kinds of problems associated with memory models.
memory leak - you dynamically allocate memory and never release it.
double free - you dynamically allocate memory and release it multiple times
accessing after free - you dynamically allocate memory then release and access that memory after release.

Memory leak on deallocating char * set by strcpy?

I have a memory leak detector tool which tells me below code is leaking 100 bytes
#include <string>
#include <iostream>
void setStr(char ** strToSet)
{
strcpy(*strToSet, "something!");
}
void str(std::string& s)
{
char* a = new char[100]();
setStr(&a);
s = a;
delete[] a;
}
int main()
{
std::string s1;
str(s1);
std::cout << s1 << "\n";
return 0;
}
According to this point number 3 it is leaking the amount I allocated (100) minus length of "something!" (10) and I should be leaking 90 bytes.
Am I missing something here or it is safe to assume the tool is reporting wrong?
EDIT: setStr() is in a library and I cannot see the code, so I guessed it is doing that. It could be that it is allocating "something!" on the heap, what about that scenario? Would we have a 90 bytes leak or 100?
This code does not leak and is not the same as point number 3 as you never overwrite variables storing pointer to allocated memory. The potential problems with this code are that it is vulnerable to buffer overflow as if setStr prints more than 99 symbols and it is not exception-safe as if s = a; throws then delete[] a; won't be called and memory would leak.
Updated: If setStr allocates new string and overwrites initial pointer value then the pointer to the 100 byte buffer that you've allocated is lost and those 100 bytes leak. You should initialize a with nullptr prior to passing it to setStr and check that it is not null after setStr returns so assignment s = a; won't cause null pointer dereference.
Summing up all the comments, it is clear what the problem is. The library you are using is requesting a char **. This is a common interface pattern for C functions that allocate memory and return a pointer to that memory, or that return a pointer to memory they own.
The memory you are leaking is allocated in the line char* a = new char[100]();. Because setStr is changing the value of a, you can no longer deallocate that memory.
Unfortunately, without the documentation, we cannot deduce what you are supposed to do with the pointer.
If it is from a call to new[] you need to call delete[].
If it is from a call to malloc you need to call std::free.
If it is a pointer to memory owned by the library, you should do nothing.
You need to find the documentation for this. However, if it is not available, you can try using your memory leak detection tool after removing the new statement and see if it detects a leak. I'm not sure if it is going to be reliable with memory allocated from a library function but it is worth a try.
Finally, regarding the question in your edit, if you leak memory you leak the whole amount, unless you do something that is undefined behavior, which is pointless to discuss anyway. If you new 100 chars and then write some data on them, that doesn't change the amount of memory leaked. It will still be 100 * sizeof(char)

Memory deallocation of pointer variable in c++

If I take a block of memory by the following line .
int* a = new int[10];
Then for freeing the memory , the code would be
delete [] a;
But if I take a pointer of single memory segment like the following
int* a = new int;
And then insert a array of data like following .
for(int i=0;i<10;i++)
{
a[i]= i ;
}
So to free the first memory segment that pointer "a" is pointing, the code would be like following
delete a;
But Here I inserted 9 more data from the memory that pointer "a" is pointing .So I am using actually 10 memory segment here . how can I free all this 10 memory ? Please help me to get the answer .
how can I free all this 10 memory ?
You can't and you shouldn't because the moment you tried to "insert a array of data like following" you have entered Undefined Behavior land for writing to a location that you didn't allocate with new in the first place. You asked for a single int, you got a single int. Don't write past it.
You allocated only one int. Memory from a[1] to a[9] may be assigned to other objects and you may corrupt them.
P.S. Btw you can not free memory that you did not allocate in any case.
new int allocates space for one int value. You cannot legally pretend that it's an array of ten int values, and the compiler won't generate code to expand the allocated memory if you go out of bounds. The code you wrote produces undefined behavior. The fact that it compiled and ran doesn't change that; sooner or later it will cause problems.
To allocate an array that can hold 10 int values, use your first expression: new int[10]. That will allocate space for ten int values.
To allocate an array that can be expanded at will, use std::vector<int>.

Why am I getting 4 as output after running code in visual studio 2010

int main()
{
int *pnPtr = new int;
delete pnPtr;
*pnPtr = 4;
cout<<*pnPtr;
}
Ans) 4 while I tried to execute in visual studio 2010.
Please, explain me how 4 is displayed as output?
what did you expect it to return?
Understand, that delete only frees the allocated memory pointed at, but leaves the pointer as it is. You can still use the pointer to do something to the pointed address.
int main()
{
int *pnPtr = new int; // allocate memory, pnPtr now points to it
delete pnPtr; // delete allocated memory, pnPtr still points to that location
*pnPtr = 4; // set memory at pointed address to 4
cout<<*pnPtr;
}
The pointer pnPtr still points to somewhere in memory, calling delete does not change the value of pnPtr itself. The memory is just no longer allocated for your process.
delete does not change the value of the pointer, it destroys the int size memory association but if not reallocated then it can be available. That has happened in your case.
Issue is due to Dangling pointers that arise during object destruction, when an object that has an incoming reference(pointer) is freed or de-allocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the de-allocated memory.
Assume if the system reallocates the previously freed memory to another process, if the original program then de-references the (now) dangling pointer, unpredictable behavior may result, as the memory may now contain completely different data. This is especially the case if the program writes data to memory pointed by a dangling pointer a silent corruption of unrelated data may result, leading to:
Subtle bugs that can be extremely difficult to find, or
cause segmentation faults or
general protection faults.
So, it is recommended to reset the freed/deleted pointer as follows:
int main()
{
int *pnPtr = new int;
delete pnPtr;
pnPtr = null;
// To-do Logic
return 0;
}