allocated memory after reasignment of pointer - c

I have two pointers:
1.
double *a, *b;
a = (double *) malloc (N*sizeof (double));
b = (double *) malloc (N*sizeof (double));
that point to huge memory space that I allocate using malloc. and assign values.
then if I do,
a=b;
a points to array b was pointing to.
What happens to memory allocated to a? Is following better alternative:
free(a);
a=b;
free(b);
or only
a=b;
free(b);
or a=b;
free(a);
or is it illegal?
Is it different if a is global and b is local?

In your example a=b creates a memory leak. Block of memory previously pointed to by a becomes impossible to free, because your program no longer has a pointer to it. This may not lead to an immediate problem, but over time your program runs out of memory, and mallocs start returning NULL.
Calling free(a) prior to reassignment fixes this problem. Once you assign a=b, you need to be careful with using a after calling free(b), because a becomes a dangling pointer.
Is it different if a is global and b is local?
Scope of the pointer does not matter here. The pointer has to be considered independently of the block of memory to which the pointer is pointing. The block is allocated in dynamic memory; the pointer to the block could be anywhere - static, automatic, or dynamic.

What you're doing causes the memory that you allocated for a to be leaked. That means you loose the information where it is stored in memory because you overwrite the pointer with b. If you want to assign the pointers like you do, the solution you yourself proposed
free(a);
a=b;
free(b);
would work. But keep in mind that after freeing b, a points to an invalid location, because you free'd the memory. So accessing a[0] will crash the program.

When you do a=b, a points to the array being pointed to by b. Then, the only memory you would want to free is the array initially pointed to by a. For doing that,
free(a);
a=b;
Here, you are freeing the memory being pointer to by a and making a point to the memory being pointed to by b. If you first do a=b, you have a pointing to the array pointed to by b, but are left with no way to access the memory that was earlier being pointed to by a. So, you should free a first. Moreover, if you free b later, all you would be left is with a and b both pointing to NULL.

Related

Does this specific code contain memory leakage?

int* a = (int*)malloc(5);
int* b = a;
free(b);
Is there memory leakage? If so, why does this occur?
This doesn't leak memory, you free what you allocate, but both a and b are invalid after the free so using either of them is undefined behaviour.
No, this is perfectly safe. (Though you shouldn't cast malloc(). Casts are evil and should be avoided whenever possible. malloc() returns void *, which you never need to cast to a different pointer type)
In your case, there is no memory leakage but these pointers are called Dangling pointers.
Because you are delete object from memory but pointers still pointing same memory location.
{
int* a = (int*)malloc(5);
int* b = a;
free(b); // a and b dangling now
a = b = NULL; //reset pointers // a and b are no longer dangling
}

C - malloc and automatic storage

I understand that variables declared within a function have automatic storage. Does this mean it's not necessary to free pointers (p below) that have been explicitly allocated within a function call using malloc?
void f() {
int *p;
p = malloc(sizeof(int));
*p = 1;
printf("%p %d\n", p, *p); // 0x7fc135c02850 1
free(p); // is this necessary?
}
int main() {
f();
}
(Note that I used a pointer to an int here, but the question applies to any pointer that's a return value of malloc and friends.)
I'm guessing no, since malloc allocates memory on the heap and not the stack; thus the memory p points to won't automatically be deallocated when the stack frame for f() is popped.
p itself is automatic storage, and it will disappear when the function ends. What it points to however does need to be free()'d, at some point. For example, you could return the malloc()'d memory from the function, and free() it later on - p has still disappeared
The memory you allocate with malloc() needs to be free()'d. In your case, automatic storage applies to the variable p itself, but not to the memory you allocated! When you use free(p), you free the memory p points to and not the p variable itself.
Correct, a call to free is necessary.
If you ask for memory allocate manually, you must free manually the space you asked for. So free is necessary there

Reassigning to a pointer variable after freeing it [duplicate]

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.

Will the Heap Scope be freed successfully while the Pointer Value was changed?

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.

Difference between dangling pointer and memory leak

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

Resources