I've got the following faulty piece of code in C and I am wondering if there will be a memory leak or if there will be a pointer which is pointing to a free memory location.
int* p = (int*) malloc(sizeof(int));
p = NULL;
free(p);
Yes it will leak memory. You assign p to NULL before freeing the contents it's pointing to. One quick change will fix it:
int* p = malloc(sizeof(int));
free(p);
p = NULL;
The difference here is we give free the address allocated by malloc before setting p to NULL. In general setting a pointer to NULL will not free the contents, but will allow you to check if the pointer is valid or not which can have a lot of practical applications.
You will have a memory leak.
After you assign NULL to p, you no longer have a way to refer to the memory you allocated with malloc.
Your call to free will try to free NULL, doing nothing.
The following will correctly free the memory:
int *p = malloc(sizeof(int));
free(p);
p = NULL;
Note that you don't need to set p to NULL after freeing, you only really need the first two lines.
Related
I would like to know, when is the pointer p released in the code? Is it considered as a local variable and released at the end of foo function?
Also, when is *p released? I'm assuming it's never released.
I know that free releases the memory allocated by malloc. But I'm having trouble understanding the difference between p and *p, which one is considered to be "the memory" which is released ?
int foo()
{
int *p = (int*) malloc(sizeof(int));
.
. //free is not called
}
Inside a function body, int *p tells the compiler (or C implementation) to allocate memory for p. This allocation is automatic, and the release of the memory used for p is automatic when execution of the block the declaration is in ends.
When malloc(sizeof(int)) executes, it attempts to allocate enough memory for an int. This allocation is manual. The memory is released only when the program executes a call to free or some related routine that frees memory (such as realloc to allocate new memory and free the old memory).
The allocations of the memory for p and the memory that p points to are unrelated. There is no binding between p and *p other than the fact that the address of *p is is stored in p. You could do this:
{
int *q;
{
int *p = malloc(sizeof *p);
// Now p points to allocated memory.
*p = 3;
q = p;
// Now q points to the allocated memory.
}
// Now p no longer exists in the C model of computing.
// The memory used for p has been released.
// The memory allocated with malloc is still allocated.
printf("%d\n", *q); // Prints “3”.
free(q);
// Now the allocated memory has been released.
}
After the call to malloc, p will contain the address of the memory allocated by malloc.
So p is a (local) variable and *p is the allocated memory.
The allocated memory (*p) is released by a call to free, which never occurs in your code (this is called a "memory leak").
The local variable p is on the stack and is automatically released when the function returns (but *p is not automatically released!)
There are two pieces of memory involved - the variable p, and the int object p points to.
int * int
+–––+ +–––+
p: | | –––> | |
+—––+ +–––+
Space for the variable p is allocated on entry to foo and released when the function exits.
Space for the int object that p points to (which we refer to with the expression *p) is allocated by the call to malloc, and is not released until you call free (or until the program terminates).
When foo exits, the variable p ceases to exist. The memory that p pointed to is still allocated, but unfortunately you can no longer access it.
I´m kind of new to using dynamic memory in C and I was wondering if there was any diference between using realloc() to allocate to a different pointer and using realloc() to allocate the same pointer.
For example:
int *ptr = calloc(10,sizeof(int))
ptr=(int*)realloc(ptr,20);
and
*ptr3;
int *ptr = calloc(10,sizeof(int))
ptr3=(int*)realloc(ptr,20);
I´ve already executed both codes and I see no real diference between both codes (nor between the values of the opinters nor the memory allocations).
Thank you.
The difference occurs in the former case when realloc fails; in that case, it returns NULL, but doesn't free the original ptr you passed it. By directly reassigning ptr, you guarantee a memory leak when realloc fails, because you no longer have the original pointer to free.
The canonical/correct usage seen here uses two pointers, one persistent, one as a temporary. The result of realloc is always put in the temporary so it can be checked (and the persistent pointer free on failure). After reallocation is known to have succeeded, the temporary pointer replaces the persistent (which is guaranteed to either be the same as the temporary, or if the allocation could not be done in place, invalid).
For the first case, if realloc fails it returns a null pointer.
You would then be assigning that null pointer to ptr making it impossible to free the memory that was originally pointed to by ptr.
Instead, do something like below:
int* p = malloc( 10 * sizeof( int ) );
/* Take note of the memory size I'm requesting in the
realloc call compared to yours. */
int* tmp = NULL;
if ( ( tmp = realloc( p, 20 * sizeof( int ) ) ) == NULL ) {
/* We failed to find available memory, but we're
still on the hook for freeing the memory pointed to by p. */
free( p );
return;
}
/* We were successful in either extending the memory pointed to by p
or a new block of memory was allocated for us and the memory pointed to by p
was copied over for us. In either case, you do not have to free p
before assigning tmp to p. */
p = tmp;
I have a question in regards to creating a dynamic array.
int *p;
p = malloc( 3 * sizeof( int ) );
// initializes elements in the array
for ( int i = 0; i < 3; ++i ) {
*p++ = i * 4;
}
how can i free the memory i just allocated? for some reason, i find much easier deallocating a two dimensional array than one LOL. It's been along time since the last time i used C.
if i do the following:
free( p ); // will probably get an error.
Another thing in regards to pointers. I tried this:
int * p = malloc( sizeof( int ) );
*p = 4;
printf( "%d\n", *p ) // prints 4 as expected
free( p );
printf( "%d\n", *p ) // still prints the number 4!!!
the free function should release the block of memory that p points to. how is it that printf stills prints 4 then?
Malloc() returns a pointer to the allocated block. Keep it for future use with free().
Index your array with integer OR walk through it with a pointer, but keep the original address stored somewhere.
You can do like this
int *p = malloc(3 * sizeof(int));
for( int i = 0; i < 3; i++)
p[i] = 4*i;
// .....
free(p);
or
int *p = malloc(3 * sizeof(int));
int *q = p;
for( int i = 0; i < 3; i++)
*q++ = 4*i;
// .....
free(p);
In the first case, you just write free(p) as you only allocated one block of memory.
What you are doing in the second case is undefined behaviour. It might print 4, it might crash, it could do literally anything. The chances are that the implementation is just marking that location as reusable, but not actually clearing it out (why should it, it's a waste of time)
free(p) de allocates memory pointed by p. But p still having memory address which is de allocated by free(p). De-allocation means that block of memory added to list of free memories which is maintained by memory allocation module. When you print data pointed by p still prints value at address because that memory is added to free list and not removed.
how can i free the memory i just allocated?
You could do something like this
int *p;
p = malloc( 3 * sizeof( int ) );
// initializes elements in the array
for ( int i = 0; i < 3; ++i ) {
p[i] = i * 4;
}
this would not change p, so you could use free(p) to free it.
If you need to change p, you should remember its original value in another variable, and call free() on that original value, such as
int *op;
op = p;
/* do something that changes `p` */
free(op);
how is it that printf stills prints 4
What you did, access a dynamically allocated memory region after you freed it, will lead to undefined behavior. It could print 4, it also could crash or do something really wild.
Malloc ==> Only allocate the memory (not changing memory data to NULL )
Free ==> Only It will release the allocated resources on the pointer,(not changing memory data to NULL )
In both cases user has the responsibly to set appropriate value if required.
In first case you can still free the memory by taking the pointer back to the first element's address and then calling free(p) like:
p = p-3;
free(p);
Reason : malloc store some information about how much memory need to be freed once allocated dynamically that's why you need to point it back to the start so that free can read that information and free exactly 3 int memory allocated by malloc.
In your second case it is still printing is not universal result, output can be anything even program may crash.
Reason : free do not do anything special with the memory it only add it back to the FREE LIST it maintains for the memory available for dynamic allocation.
It is only up-to the programmer that they do not dereference the after calling free on it.
how can i free the memory i just allocated?
When we want to free a memory chunk previously allocated by malloc(), we use the free function. This function accepts a char pointer to a previously allocated memory chunk, and frees it - that is, adds it to the list of free memory chunks, that may be re-allocated. Use free(p).
how is it that printf stills prints 4 then?
Usage Of free():
Several notes about free():
The size of the chunk was stored by malloc() previously in its memory map, and that is how free() knows how many bytes to free.
The freed memory is not being cleared or erased in any manner. This is why accessing memory that was just freed often does not cause a crash - any data in it is still the same as before calling free().
The free() function cannot nullify pointers to the given memory chunk that might still exist in our program. After we call free(), it is up to us (the programmers) not to try and dereference pointers that still point to that memory chunk. Such pointers are known as 'dangling pointers' - they point to memory that was already freed, and thus they should NOT be dereferenced again, unless they are assigned the address of a different (not-freed) memory chunk.
When using realloc is the memory automatically freed? Or is it necessary to use free with realloc? Which of the following is correct?
//Situation A
ptr1 = realloc(ptr1, 3 * sizeof(int));
//Situation B
ptr1 = realloc(ptr2, 3 * sizeof(int));
free(ptr1);
ptr1 = ptr2;
Neither is correct. realloc() can return a pointer to newly allocated memory or NULL on error. What you should do is check the return value:
ptr1 = realloc(ptr2, 3 * sizeof(int));
if (!ptr1) {
/* Do something here to handle the failure */
/* ptr2 is still pointing to allocated memory, so you may need to free(ptr2) here */
}
/* Success! ptr1 is now pointing to allocated memory and ptr2 was deallocated already */
free(ptr1);
After ptr1 = realloc(ptr2, 3 * sizeof(int)); ptr2 is invalid and should not be used. You need to free ptr1 only. In some cases the return value of realloc will be the same value you passed in though.
You can safely consider ptr1=realloc(ptr2, ... as equivalent to this:
ptr1 = malloc(...);
memcpy(ptr1, ptr2, ...);
free(ptr2);
This is what happens in most cases, unless the new size still fits in the old memory block - then realloc could return the original memory block.
As other allocation functions, realloc returns NULL if it fails - you may want to check for that.
realloc() automatically frees the original memory, or returns it unchanged (aside from metadata) if you realloc() to a smaller size or there is unallocated memory available to simply expand the original allocation in place.
According to http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/, realloc returns the new memory block if the reallocation is successful, keeps the original memory block if not. Standard usage would look like this:
ptr2 = realloc(ptr1, new_size);
if (ptr2 == NULL) {
//ptr1 still contains pointer to original array
} else {
//ptr2 contains new array, ptr1 is invalid
}
In both situations, ptr1 must be freed.
Situation B is more complex because ptr2 potentially points to freed space. Or not. It depends on whether it could be reallocated. ptr2 should not be used after the realloc in B.
int main(void) {
int* p = (int*) malloc(sizeof(int));
int* q = (int*) malloc(sizeof(int));
*p = 10;
*q = 20;
p = q;
printf(“%d %d”, *p, *q);
free(p);
free(q);
}
Why does the above code contain use-after-free error? There's no more expression after free(p) and free(q). Obviously we are not using them anymore!
You have two problems here.
First, you are deleting the same heap variable twice:
free(p);
free(q);
Second, you have a memory-leak, because the variable created by p is no longer accessible.
Notice that onebyone's comment is really important. If you change the line:
p = q;
into:
*p = *q;
There would be no problems at all in your code :) Hello Pointers!
You set p to q, so you are free()ing it twice.
Since q and p point to the same memory at the point you are freeing them, you're effectively freeing the memory twice.
Because here:
p = q;
...you're throwing away the old value of p. You now have two copies of the pointer that was returned by the second malloc, and none of the pointer that was returned by the first malloc.
So then here:
free(p);
free(q);
...the same pointer value gets passed to free twice: use-after-free error. The other pointer value never gets passed to free at all: memory leak.
It's a fundamental memory manipulation error!
Never do so!
You allocate memory at pointer p and after that you just rewrite pointer at p=q.
Previous value of pointer you lost, p is a lost pointer!
You can never free the memory allocated above for pointer p! It's a lost memory block for p.
It's memory leak... Try to free it at line free(p) in real free memory allocated for pointer q, but not for p!.
Next line free(q) is another try to free the same memory that was freed in previous line. That will be unpredictable behavior depending on the system it may be nothing special, and may be an error at program finish.
You must replace line free(p) before line p=q.
And always before rewrite pointer with previously allocated memory free them! Consider it a strict rule!