Allocating memory for one dimensional array in C - c

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.

Related

Is there any difference between allocating realloc() to a different pointer and allocating realloc() to the same one?

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;

Can't I directly put head=NULL if i want to destroy linked list and free memory?

Why do we need free()? Putting the head node as NULL does similar work, doesn't it?
Why do we need free()?
The function free is used to free a dynamically allocated memory.
Putting the head node as NULL does similar work, doesn't it?
Putting NULL in the pointer to the head node does not free all dynamically allocated memory in the list neither for the head node nor for other nodes. This leads to loosing the address of the first dynamically allocated node and as a result you will get numerous memory leaks because the memory becomes inaccessible (but not freed)..
Consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p1 = malloc( sizeof( int ) );
*p1 = 10;
printf( "*p1 = %d\n", *p1 );
int *p2 = p1;
p1 = NULL;
printf( "*p2 = %d\n", *p2 );
free( p2 );
return 0;
}
Its output is
*p1 = 10
*p2 = 10
In the program there is dynamically allocated a memory for an object of the type int and the address of the allocated memory was assigned to the pointer p1.
After assigning NULL to the pointer p1 the address of the allocated memory is not stored in this pointer any more.
So if the address was not assigned to the second pointer p2 then the address of the allocated memory would be lost forever and we could not free the memory.
Only due to having a copy of the address in the pointer p2 we can free the allocated memory.
Thus setting a pointer to NULL only changes the value stored in the pointer. The allocated memory is not touched in any way.
They are not equivalent.
In C, if you explicitly allocated memory (e.g., by using malloc), you need to explicitly free it (by using free).
If you just assign head = NULL, you won't be able to access the following elements in the linked list, but their memory will still be allocated - the process will still hold this memory, and you'll have a memory leak on your hand.
Because there is no garbage collector in C. This means you should collect your garbage yourself.
Everything you allocated on the heap has to be deleted manually.
Forgetting to do it is called memory leak.

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.

Accessing Arrays created Using Malloc

what is wrong with this?
why wont it work? its showing segmentation fault(core dumped)
Cant we use a[I]?
#include<stdio.h>
int main()
{
int *a,i,n;
scanf("%d",&n);
*a=malloc(n*sizeof(int));
for(i=0;i<n;i++)
a[i]=i;
free(a);
return(0);
}
Please enable compiler warnings; something should be screaming at you about:
*a=malloc(n*sizeof(int));
This says:
Allocate some memory.
Assign that address to the integer pointed to by a (which is uninitialized and points to no known location).
a itself is still pointing nowhere in particular.
Then:
a[i]=i;
writes into that random space.
You want to say:
a = malloc(n * sizeof(int));
*a = malloc( n * sizeof(int) ); should be a = malloc ( n * sizeof(int) );
malloc() allocates the storage and returns a pointer to the first byte.
As a is pointer variable is should point to the address.
Where as *a is incorrect in this case, because * along with pointers is used for de-referencing.
You are setting the memory address pointed to by a to the address returned by malloc. Since a is not yet initialized, you are setting an undefined part of memory to the address returned by malloc.
*a=malloc(n*sizeof(int));
Instead, set the pointer itself
a=malloc(n*sizeof(int));

Passing pointers with space allocated by malloc

I've just written a function that returns a pointer to a block of memory allocated by malloc. If I call free() on the returned pointer, will this free the memory?
I tried reading up on this, but I can't find anything that says whether you can call a different pointer pointing to the same location and whether that will free all the memory or not.
This is probably majorly basic, I think I can't find the info because I'm searching for it wrong.
Any help appreciated!
Yes calling free will free the memory. Its not the pointer that get freed but the memory that the pointer points to that is freed.
You must pass to free() the value obtained from malloc().
int *x = malloc(42 * sizeof *x);
int *p = &x[0];
free(p); /* ok, same as free x; x and p have the same value */
Edit: another example
int *x = malloc(42 * sizeof *x);
for (k = 0; k < 24; k++) *x++ = 0; /* zero first 24 elements */
free(x - 24);
It's not entirely clear what you're asking here, but if what you're asking is:
Can I call free() on a pointer which points to a location within the allocated block?
then the answer is "no" -- you must pass free() the exact pointer which you got back from malloc(). Trying to free() an internal pointer, or a pointer to memory which was not allocated by malloc(), memory corruption or a crash are likely to occur.

Resources