While copying a pointer, is the memory copied as well? - c

Consider the code below:
int * a = malloc(sizeof *a * 10);
int * b;
b = a; //Is there an operation "b = malloc(sizeof *a * 10);" occuring?
free(b); //will the memory of 'a' be free?
Also, how can I test whether a piece of memory is released or not?

b = a; //Is there an operation "b = malloc(sizeof *a * 10);" occuring?
No, assigning a to b merely sets b to have the value of a. Since a is a pointer, b then points to the same place that a points to.
free(b); //will the memory of 'a' be free?
Yes, after b = a;, free(b); will free the memory that a points to. Note that this is not the memory of a, it is the memory a points to. C does not create or maintain any connection or ownership relation between a pointer and the memory it points to. Pointers are merely things with values that are addresses.
The fact that memory was initially allocated and assigned to a with a = malloc(…) does not create any special relationship between a and the memory. Other pointers can be used to access and free the memory, and the value of a can be changed to something entirely unrelated without affecting the memory.

Related

Passing pointers as argument

int *tomato(int *a, int *b) {
int *foo = (int*)malloc(sizeof(int));
*foo = *a + *b;
return foo;
}
In this function I have foo that is allocated in heap and returns a pointer to int, but are the pointers *a and *b in the function arguments also allocated in heap? I am a bit confused here, generally, arguments are allocated in stack.
The pointers are local variables in the tomato function, just like foo.
The values that they point to can be allocated anywhere. For instance, you can call it like this:
int foo = 1;
int *bar = malloc(sizeof(int));
*bar = 3;
int *result = tomato(&foo, bar);
a will point to a the foo variable, while b will point to the memory allocated by malloc.
Parameters in C are not necessarily allocated in the stack (*), but their scope will necessarily be restricted to the tomato function block, and they will necessarily be passed by value.
When you dereference a and b in the assignment *foo = *a + *b, you are interpreting the memory address stored in pointers a and b as integers, summing them, and writing the result in the memory address stored in pointer foo (which, in your example, happens to be in the heap).
After the assignment, you could change a and b at will by assigning different memory addresses to them (i.e. pointers), and there would be no consequence to any external memory references as their scope is limited to the function block (e.g. a = foo). If, however, you changed the memory contents referred by them (e.g. *a = 0), this would become visible outside the scope of the function as you would be writing on a memory space (stack or heap) allocated somewhere else.
(*) Parameters may not be passed in memory (i.e. stack) to functions. Depending on the compiler/architecture, they may be directly assigned to a processor register. Either way, this is a transparent compiler optimization and you don't have to worry about it... the parameters will behave just the same.

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
}

Memory segments stack and heap

i've looked over so many topics and i still could not find out why this happens:
struct B
{
int _arr[5];
};
struct A
{
struct B * _pb;
};
int main() {
int i;
struct B b;
struct A *pa = (struct A*)malloc(sizeof (struct A));
for (i=0;i<5;++i)
{
b._arr[i] = i;
}
pa->_pb=&b;
Struct A a = *pb;
}
How come pa found on stack and *pa is found on heap! both are local variables and should be only valid through scope so it should be on stack.
also why is ‪a._pb->_arr[2] on stack should not be on heap? can anyone clarify for me when it should be on stack and when on heap
The variable pa is on the stack. The memory it points to is on the heap.
Somewhat graphically a pointer variable can be describes like this:
+----+ +--------------------------------+
| pa | --> | allocated memory for structure |
+----+ +--------------------------------+
The two locations illustrated above (pa and the memory it points to) can be in different "segments", or they can be in the same.
And a._pb->_arr[2] is on the stack because a._pb is pointing to b which is on the stack.
Lastly a note about the "stack". While it's common to store local variables on the stack, the C specification doesn't say anything about it. Local variables are really automatic variables, and the C specification only specifies the semantics of those not where they should be stored.
First off, the C standard says nothing about stacks and heaps. Those are implementation details of a given compiler. That being said, most compilers for desktop applications use both of these.
You are correct that pa is local to the main function and therefore resides on the stack. *pa however is not a local variable. It is an expression which evaluates to an instance of struct A.
In this case, the malloc function returns a pointer to a block of memory big enough for a struct A and the value of that pointer is stored in pa.
Generally speaking, anything returned by malloc, realloc, or calloc lives in the heap, while variables declared local to a function (even pointer variables which may point to the heap) reside on the stack.
Short answer: *pa (what pa points to) is found on the heap because that's where you allocated the memory using malloc(). The variable pa, the pointer itself, is allocated on the stack because it's a local variable.
Long answer: Make sure you note the difference between a pointer and what the pointer refers to.
A declaration like this:
int a[5]
Tells the compiler to reserve space for a 5-element array, while a declaration like this:
int *a;
Tells the compiler to reserve space for a pointer. If you want the pointer to refer to an array then you need to allocate the memory, usually on the heap using malloc() and then release it when you're done using free().
And just to confuse things, in the C language, the array operator, [], is equivalent to the pointer arithmetic *() so that these two statements are wholly equivalent, regardless of whether a was declared as a pointer or an array:
a[2] = 5;
*(a + 2) = 5;
Digression: Which leads to some amusing possibilities. The above two statements are also equivalent to this one:
2[a] = 5;
Because addition is commutative in C:
2[a] = 5;
*(2 + a) = 5;
*(a + 2) = 5;
a[2] = 5;
But this absolutely does not work in C++ for reasons that are too far afield for this digression.

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.

Resources