I don't understand the difference between a dangling pointer and a memory leak. How are these two terms related?
A dangling pointer points to memory that has already been freed. The storage is no longer allocated. Trying to access it might cause a Segmentation fault.
Common way to end up with a dangling pointer:
char *func()
{
char str[10];
strcpy(str, "Hello!");
return str;
}
//returned pointer points to str which has gone out of scope.
You are returning an address which was a local variable, which would have gone out of scope by the time control was returned to the calling function. (Undefined behaviour)
Another common dangling pointer example is an access of a memory location via pointer, after free has been explicitly called on that memory.
int *c = malloc(sizeof(int));
free(c);
*c = 3; //writing to freed location!
A memory leak is memory which hasn't been freed, there is no way to access (or free it) now, as there are no ways to get to it anymore. (E.g. a pointer which was the only reference to a memory location dynamically allocated (and not freed) which points somewhere else now.)
void func(){
char *ch = malloc(10);
}
//ch not valid outside, no way to access malloc-ed memory
Char-ptr ch is a local variable that goes out of scope at the end of the function, leaking the dynamically allocated 10 bytes.
You can think of these as the opposites of one another.
When you free an area of memory, but still keep a pointer to it, that pointer is dangling:
char *c = malloc(16);
free(c);
c[1] = 'a'; //invalid access through dangling pointer!
When you lose the pointer, but keep the memory allocated, you have a memory leak:
void myfunc()
{
char *c = malloc(16);
} //after myfunc returns, the the memory pointed to by c is not freed: leak!
A dangling pointer is one that has a value (not NULL) which refers to some memory which is not valid for the type of object you expect. For example if you set a pointer to an object then overwrote that memory with something else unrelated or freed the memory if it was dynamically allocated.
A memory leak is when you dynamically allocate memory from the heap but never free it, possibly because you lost all references to it.
They are related in that they are both situations relating to mismanaged pointers, especially regarding dynamically allocated memory. In one situation (dangling pointer) you have likely freed the memory but tried to reference it afterwards; in the other (memory leak), you have forgotten to free the memory entirely!
Dangling Pointer
If any pointer is pointing the memory address of any variable but after some variable has deleted from that memory location while pointer is still pointing such memory location. Such pointer is known as dangling pointer and this problem is known as dangling pointer problem.
#include<stdio.h>
int *call();
void main(){
int *ptr;
ptr=call();
fflush(stdin);
printf("%d",*ptr);
}
int * call(){
int x=25;
++x;
return &x;
}
Output: Garbage value
Note: In some compiler you may get warning message returning address
of local variable or temporary
Explanation: variable x is local variable. Its scope and lifetime is within the function call hence after returning address of x variable x became dead and pointer is still pointing ptr is still pointing to that location.
Solution of this problem: Make the variable x is as static variable.
In other word we can say a pointer whose pointing object has been deleted is called dangling pointer.
Memory Leak
In computer science, a memory leak occurs when a computer program incorrectly manages memory allocations.
As per simple we have allocated the memory and not Free other language term say not release it call memory leak it is fatal to application and unexpected crash.
Pointer helps to create user defined scope to a variable, which is called Dynamic variable. Dynamic Variable can be single variable or group of variable of same type (array) or group of variable of different types (struct). Default local variable scope starts when control enters into a function and ends when control comes out of that function. Default global vairable scope starts at program execution and ends once program finishes.
But scope of a dynamic variable which holds by a pointer can start and end at any point in a program execution, which has to be decided by a programmer. Dangling and memory leak comes into picture only if a programmer doesnt handle the end of scope.
Memory leak will occur if a programmer, doesnt write the code (free of pointer) for end of scope for dynamic variables. Any way once program exits complete process memory will be freed, at that time this leaked memory also will get freed. But it will cause a very serious problem for a process which is running long time.
Once scope of dynamic variable comes to end(freed), NULL should be assigned to pointer variable. Otherwise if the code wrongly accesses it undefined behaviour will happen. So dangling pointer is nothing but a pointer which is pointing a dynamic variable whose scope is already finished.
Memory leak: When there is a memory area in a heap but no variable in the stack pointing to that memory.
char *myarea=(char *)malloc(10);
char *newarea=(char *)malloc(10);
myarea=newarea;
Dangling pointer: When a pointer variable in a stack but no memory in heap.
char *p =NULL;
A dangling pointer trying to dereference without allocating space will result in a segmentation fault.
A pointer pointing to a memory location that has been deleted (or freed) is called dangling pointer.
There are three different ways where Pointer acts as dangling pointer.
De-allocation of memory
Function Call
Variable goes out of scope
—— from https://www.geeksforgeeks.org/dangling-void-null-wild-pointers/
A pointer pointing to a memory location that has been deleted (or freed) is called dangling pointer.
#include <stdlib.h>
#include <stdio.h>
void main()
{
int *ptr = (int *)malloc(sizeof(int));
// After below free call, ptr becomes a
// dangling pointer
free(ptr);
}
for more information click HERE
Related
I was wondering where a struct would be allocated in memory if I have something like this.
typedef struct {
int c;
} A;
A * a = (A)* malloc(sizeof(A));
a -> c = 2;
C would be allocated in the heap area, is that right?
Moreover, if I free the memory with
free(a);
What happens to the memory area occupied by C?
A * a = (A)* malloc(sizeof(A));
This line is incorrect, if you want to make an explicit cast, the syntax is (A*), not (A)*.
Anyway, yes, malloc allocates memory on the heap (in general and on non exotic system). What happens after depends on the OS and the implementation of the libc you use. Most often however, the memory freed is kept in a list for future use by malloc.
First of all you need to allocate the memory like A * a = (A*) malloc(sizeof(A));. In C when you allocate memory to a struct dynamically you need to provide total size of that struct and the return type conversion from void* to your data type. So your malloc call will allocate that much of memory and returns a void pointer to the first byte of that block of memory location.
So do not confuse that declaring variable inside a struct will be allocated from stack. Please see below:-
int c;// c is a automatic variable and memory will be allocated from stack
typedef struct {
int c;// c is not a automatic variable it is simply a data member of `struct A`
} A;
So in the second case memory will be allocated to c only when malloc will be called at run time that is dynamically and from heap. So your free call will simply release that memory at run time.
But
typedef struct {
int c;// c is not a automatic variable it is simply a data member of `struct A`
} A;
A a;// Here 'a' is a automatic variable so 'int c' is also become automatic here
//and memory for the entire struct A will be allocated from stack and
//you no need to use `free` here
Hope this is help.
A * a = (A)* malloc(sizeof(A));
Where a struct would be allocated in memory?
In C, the library function malloc allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. The memory is given by the operating system. If memory is not available NULL pointer is returned.
There is no need for casting of malloc in C. Your code has a typo, if anything it should be (A *).
What happens to the memory area occupied by C?
When the memory is no longer needed, the pointer pointing to the allocated memory should be passed to free which deallocates the memory so that it can be used again. For free(NULL); the function does nothing.
C11 standard (ISO/IEC 9899:2011):
7.22.3.3 The free function
Synopsis
#include <stdlib.h>
void free(void *ptr);
Description
The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation. If ptr is
a null pointer, no action occurs. Otherwise, if the argument does not
match a pointer earlier returned by a memory management function, or
if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
Fistly, C is a case-sensitive language.
int c is not the same as int C, so you might want to edit that in your question.
Now, lets answer your questions:
C would be allocated in the heap area, is that right?
Yes it is allocated from heap, subject to availability.
If you forget to release memory that was allocated, you will exhaust it.
Lets see what C11 standard says, C11 - Section 7.22.3 states,
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
Thats should suffice to justify why explicit typecasting in statement
A * a = (A)* malloc(sizeof(A));
is not required. So it should be
A * a = malloc(sizeof(A));
followed by test if a is NULL, if it is NULL, you shouldn't continue with further access.
What happens to the memory area occupied by C?
Again, referring to C11 standard, C11 - Section 7.22.3.3 which states,
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
a in your code is equivalent to ptr above. Once freed, you can consider that the memory is returned to heap-pool for fresh allocations. There is no memory occupied by c now, and hence an access to c results in Undefined Behavior.
Refer C11 Standard, section J.2 Undefined Behavior:
An object is referred to outside of its lifetime (6.2.4).
The value of a pointer to an object whose lifetime has ended is used (6.2.4).
A * a = (A)* malloc(sizeof(A));
The compiler must be giving an error on this statement and if I am guessing correctly you want to cast the malloc return with (A *) which you should not do [check this].
In C language, a structure is a user-defined datatype which allows us to combine data of different types together and size of a structure variable is
size of all member variables + size of structure padding
So, when you dynamically allocate memory of sizeof(struct name) size, a block of memory of requested size gets allocated in heap and when you pass this pointer to free(), it deallocates that whole memory block.
What happens to the memory area occupied by C?
It is deallocated.
The lifetime of a dynamically allocated object is over when it is deallocated. So, when you do free(a), the life of a and all its data members is over and it is indeterminate now.
Additional:
A point to note here about free() is that it does not change the value of the pointer (passed to it) itself, hence it still points to the same (now invalid) location.
So, when you free a dynamically allocated memory it still points to the same location which is no more valid and accessing such memory is undefined behavior. From C Standard#6.2.4p2
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
Although arrays are basically pointers, freeing char[] in C gives an error.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this gives error at run time
}
ERROR: nexc(4212,0x10038e3c0) malloc: * error for object 0x7fff5fbff54c: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
The interesting part is that, it is saying I am freeing a pointer which is not allocated.
How could this happen?
But in C++, compiler gives me a compile time error instead.
int main(void) {
char ptr[] = "Hello World";
delete ptr; // this gives error at compile time
}
like,
Cannot delete expression of type char[12]
I thought this is because of compiler handles the char[12] by allocating when the function is called and deallocating the memory when the function ends. So, I write some codes after free(ptr); before the function ends.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this still gives error at run time
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
}
This still gives error. How is this happening?
You only free what you have allocated using malloc (directly or indirectly) or related function (like realloc).
Attempting to pass a pointer not returned by malloc will lead to undefined behavior.
That you get a compiler error for delete in C++ is first and foremost because C and C++ are different languages with different rules.
And remember, an array is an array, not a pointer. Though an array can decay to a pointer to its first element in many situation (like when passing it to a function).
You only call free on dynamic memory that you've allocated using malloc, calloc &c.. Similarly, you only call delete on memory allocated with new. In your case, the C++ compiler is required to issue a diagnostic since pointer decay is not permitted to occur in this particular instance, and delete requires a pointer type.
The behaviour on attempting to call free on automatic memory is undefined.
You only need to free what was malloced.
Your ptr is not a pointer, it is an array; an automatic local (inside main()) variable. It does not need freeing and attempting to free it is a mistake.
All the static Strings will be allocated in the data section. You can't free data from this section. Threrefore, you can free only data the you have allocated with malloc (calloc / ralloc)
in C programming language, you cannot write the instruction you made for obvious reasons. First of all, it must be understood that a pointer variable is a variable like so many others with a type except that it contains only addresses, so it is called a pointer variable because it contains the address of what is in memory. A pointer is therefore an address associated with a type of data and these two elements are inseparable.
If the pointer variable contains the address of an object of the whole type, the pointed object is used to know how to interpret the bits that make up this object, as well as its size. The instruction you wrote is therefore a constant pointer to a character type stored somewhere in memory. The string is therefore probably placed in a read-only data segment and therefore you cannot modify the string or release its memory, because the pointer variable does not point to a string in a space allocated dynamically beforehand by the "malloc" or "calloc" allocation function, and that is why you have the error message.
The second error is due to a confusion of your part here too, you must understand that there is a difference between an array of characters and a pointer. In simpler terms, a pointer variable is not an array and an array is not a pointer, but access to the element is done in the same way. For an array, the characters that make up the string and end with "\0" can be changed, but the array of characters will always point to the same address in memory and the pointer can contain another address, but beware, if you allocate the memory with a pointer and then point to other pars without releasing the memory you allocated creates a memory leak.
This is the proper way of using delete ! you first have to let the compiler know that the variable ptr is dynamic by using new!
#include<iostream>
#include<new>
using namespace std;
int main(void) {
char *ptr;
try{
ptr = new char [20];
} catch(bad_alloc xa){
cout<<"error";
}
ptr= "Hello World";
cout<<ptr;
delete [] ptr;
}
This question already has answers here:
Reusing freed pointers in C
(4 answers)
Closed 5 years ago.
Is this legal to do? Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int));
free(ptr);
ptr = (int *) malloc(sizeof(int));
You aren't reassigning the pointer after freeing it, you're just reusing the ptr variable. This is perfectly fine.
First of all, as I mentioned in the comments, please see this discussion on why not to cast the return value of malloc() and family in C..
That said, yes, the (re)-assignment is fine here.
Actually, the question wording
Can you assign ptr to something after it has been freed?
should read
Can you assign ptr with something after it has been freed?
Guess what, the assignment without free-ing is also legal as per C, but it will create a memory leak as a side effect as the variable ptr was holding the return value of a memory allocator function and you need to free the memory once you're done using it. If, you re-assign the pointer without keeping a copy of the pointer, you'll lose the access to the memory allocated by allocator function and will have no ways to free() it.
In case the pointer was holding an address of statically allocated variable, you don't get to (nned to) free it and direct re-assignment is perfectly fine. think of this below snippet.
int x = 5, y = 10;
int * p = &x;
//do something with p
p = &y; //this is fine, just a re-assignment.
Yes. it is a valid in C language.
Related stack overflow question for more information: Reusing freed pointers in C
According to cwe.mitre.org:
In this scenario, the memory in question is allocated to another
pointer validly at some point after it has been freed. The original
pointer to the freed memory is used again and points to somewhere
within the new allocation. As the data is changed, it corrupts the
validly used memory; this induces undefined behavior in the process.
Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int)); /* line 1 */
free(ptr); /* line 2 */
ptr = (int *) malloc(sizeof(int)); /* line 3 */
Taking your question as:
"Is it legal to assign the address of freshly, dynamically allocated memory to a pointer (line 3), after the memory this pointer pointed to from a previous dynamical allocation (line 1) had been freed (line2)?"
Then this answer is yes.
Running line 3 would also be valid without having run line 2. Still, if not calling free() (line 2), the value assigned to ptr (line 1) is overwritten (line 3), and with this the possibility to call free() on ptr's initial value is lost, which in turn leaves the program with leaking exactly this memory allocated initially.
Is this legal to do? Can you assign ptr to something after it has been freed?
Yes, this is legal. ptr can be reassigned as many times as you want. Freeing that pointer is not necessary for reassigning it, for example
int * ptr = malloc(sizeof(int));
int *temp_ptr = ptr; // temp_ptr is pointing to the location ptr is pointing
ptr = malloc(sizeof(int)); // ptr points to new location.
Note that you should not cast the return value of malloc.
Yes you are assigning new memory on heap and its legal.
I would recommend you use realloc instead.
For the case when realloc() fails, from c11, chapter §7.22.3.5,
The realloc function returns ... a null pointer if the new object
could not be allocated.
and
[....] If memory for the new object cannot be allocated, the old
object is not deallocated and its value is unchanged.
The proper way of using realloc will be
ptr_new = realloc(ptr, sizeof(int)*2);
if (ptr_new == NULL)
{
free(ptr);
}
Also please read why should i not cast return value of malloc.
Yes. It is perfectly legal. ptr is a standalone variable that continues to exist regardless of its contents. Nothing happens to the memory location where ptr is stored. There is nothing to prevent you from assigning you any value to it. The correctness of the memory allocation ( malloc / realloc etc) is a different story, but there is nothing wrong with reusing a variable (a memory location) to store the address of a memory location.
When you declare a pointer it will be allocated for it a memory location. That location can be reassigned.
If you reassign it after having assigned it a value with a malloc() call and before to free() it, this is a memory leak. After free() you can reassign it and no leak will happen, do not forget to free() it again.
In fact, the operating systems that are useful programs that never finish will reassign all the time some fixed pointers toward processes, free them when the process finishes, etc.
The programming in which assignments are not allowed is called functional programming.
For example:
void heaptest(){
int *a;
a=(int*)malloc(1024*4);
int i=1024;
while(i--){
*a=i;
//printf("%d",*a);
a++;
}
free(a);
}
When the 'a' was used as a pointer, assume it points to address "0x20000". And the scope of this heap area is from 0x20000 to 0x21000. totally 4096 bytes.
after the while loop, the 'a' was pointed to 0x21004, which is actually out of the scope of the defined heap. if we free the heap using
free(a)
Will this heap be freed successfully?
For my observation, when I use this func in Visual Studio. it will show
Invalid address specified to RtlValidateHeap
and the value of a is 0x21004 before the free() operation whenever whether there is a printf() function in the while loop.
When I use this function on Keil-MDK for STM32F7(Cortex M7), it shows nothing but before the free operation. the value of 'a' will become 0x00000;
But when I add the printf() function shown in the code. the value of 'a' will back to the initial value 0x20000.
So, the final question is, could we change the value of the heap pointer? or assign it back to the initial value every time before the free() operation?
Will this heap be freed successfully?
It is impossible to say. You invoke undefined behavior by passing a pointer value to free() that was not returned by malloc() or one of the other allocation functions. That could turn out to manifest as freeing the block into which the pointer points, but more likely it produces an error, or worse: silent memory corruption.
Note in particular that it is the pointer value that matters. The variable, if any, in which you store the pointer value has nothing directly to do with it.
could we change the value of the heap pointer?
In the sense that the pointer is a value, no, you can no more change it than you can change the value 1. But you can cause a variable in which that value is stored to instead contain a different value. You may even be able to do so in a way that allows you to recover the original value, so as to retain the ability to free the allocated memory.
You need to free the address your were given. What you do to the code's variables in between does not matter.
This is valid:
char * p = malloc(42);
p++;
p--;
free(p);
This as well:
char * p = malloc(42);
char * q = p:
/* p += 43; */ /* Invokes UB, as making q point more then just one past the object. */
q += 42; /* Just one past the allocated memory. */
q -= 42;
free(q);
This isn't
char * p = malloc(42);
p++;
free(p);
This neither:
char * p = malloc(42);
p--;
free(p);
An address passed to free must have been obtained as the return value of malloc/calloc/etc. Passing any other pointer invokes undefined behavior.
From the MSDN page for free:
The free function deallocates a memory block (memblock) that was
previously allocated by a call to calloc, malloc, or realloc. The
number of freed bytes is equivalent to the number of bytes requested
when the block was allocated (or reallocated, in the case of realloc).
If memblock is NULL, the pointer is ignored and free immediately
returns. Attempting to free an invalid pointer (a pointer to a memory
block that was not allocated by calloc, malloc, or realloc) may affect
subsequent allocation requests and cause errors.
Keep track of the original pointer so you can later pass it to free:
void heaptest(){
int *a, a_sav;
a=(int*)malloc(1024*4);
a_sav = a; // save the original pointer
int i=1024;
while(i--){
*a=i;
printf("%d",*a);
a++;
}
free(a_sav); // free the saved pointer
}
Calling free with an argument that does not point to an adress allocated via malloc, calloc or realloc is undefined behavior. You have absolutely zero information on what it will do. Try something in this form.
void heaptest(){
// Declare a const to make sure we free the right adress in the end
int * const a = (int*)malloc(1024*size_of(int));
int i=1024;
do {
// This will loop from a[0] to a[1024] which is what I assume you meant to do
a[1024-i] = i;
} while (--i);
free(a);
}
It's hard to say if this program does what you wanted. You can change i or the index or the right hand side of the assignment to suit your needs but don't do the loop like you did because it's way more error-prone.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = malloc(sizeof(char) * 1);
ptr = "Hello World";
puts(ptr);
getchar();
}
im not a malloc() expert but isn't that code supposed to give an error since i allocated only one byte but assigned a value that contains 11 bytes to *ptr pointer ?
or does the H get stored in the place i assigned and then the rest of the string just goes in the places after it ?
You are reassigning the pointer 'ptr' to another block of memory, so you won't see any error. However, the block of memory (size 1) that you allocated is "lost" and leads to a memory leak.
When using malloc you're requesting some memory and malloc returns the first address of that memory (if it can be given). When you re-assign the pointer you're not doing anything with the memory it points to. You just change what the pointer points to.
What you're doing here is technically valid C but you're creating a memory leak because you lose the address of the malloced memory, which you must free when you're done with it.