Does this specific code contain memory leakage? - c

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
}

Related

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

Can I free memory originally allocated from another pointer?

If I allocated memory from another pointer, then declare a pointer equal to the other pointer, can I then free the memory allocated with the first pointer by using free() on the new pointer?
Example:
typedef struct foo{
int n;
char c;
} foo;
foo* bar = malloc(sizeof(foo));
foo* tmp = bar; // declaring pointer identical to other pointer
free(tmp); // can I do this to free *bar?
Yes, it is completely fine.
Your implementation of malloc will most likely mark the chunk of memory as allocated before returning a pointer to it.
Now you can have as many pointer variables as you want which point to this chunk of memory and you can free that memory by calling free on any of them.
The pointer itself doesn't contain information about whether the memory it points to has been allocated. It just points to it.
int* i = malloc(sizeof(int) * 23);
int* j = i;
free(j);
// free(i); // this is undefined behavior, the memory was already freed
Yes you can do what you are asking about. But it is not another pointer, what you are freeing is the same pointer. When malloc returns a pointer, it is essentially giving you an integer that is the address of the start of the chunk of memory that it has reserved for you. When you are done are done with the memory, you pass that address to free. As far as free is concerned, there is no difference between:
free(malloc(17));
,
void *p = malloc(17);
free(p);
or
void *p1 = malloc(17);
void *p2 = p1;
free(p2);
In all of these cases the value returned from malloc is getting to free, and that is all that matters.

Questions on use of malloc() and free()

Thanks for notice my question.
In C Primer Plus, it first writes
The argument to free() should be a pointer to a block of memory allocated by malloc(); you can’t use free() to free memory allocated by other means
which means ONE malloc(), ONE and ONLY one free().
But later it goes
It’s okay to use a different pointer variable with free() than with malloc(); what must agree are the addresses stored in the pointers.
which seems contradict to the first statement.
So my understanding is that as long as a pair of malloc() and free() share the same address there is no error, and the name of pointers doesn't matter. Am I right?
For example:
void* p = malloc (100);
void* q = p;
free (q);
...is fine. The argument for free () is the value that was returned by malloc. The sentence
"It’s okay to use a different pointer variable with free() than with
malloc()"
is actually pointless and just creates confusion - of course it is fine to use different variables as long as the value is the same.
Just remember that freeing any alias, makes all the pointers invalid
int *a, *b, *c, *d, *e;
a = malloc(42 * sizeof (int));
b = a;
c = b;
d = c;
e = d;
a[0] = 42;
b[1] = 100; // same as a[1]
c[2] = 999; // same as a[2]
d[3] = -1; // same as a[3]
e[4] = 0; // same as a[4]
free(d); // for example
// all of a, b, c, d, and e are now invalid;
Variables contain some value, which could be a pointer (i.e. a memory address).
Two variables could contain the same pointer (that is, the same address), it is called pointer aliasing.
What matters to free is to get the value of a pointer previously given by malloc (that is a memory address previously given by malloc)

allocated memory after reasignment of pointer

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.

Use after free error?

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!

Resources