dynamiclly allocate and free in C - c

void* heap = malloc(100);
char *c = heap;
strcpy(c, "Terence");
printf("heap = %s\n", heap);
free(heap);
heap = malloc(100);
printf("heap = %s\n", heap);
the output is:
heap = Terence
heap =
That is what I expect, but now I have a far more complex code, the structure is similar to the above, but the output is like:
heap = "Terence"
heap = " ren "
something like that.
It seems heap has not been cleaned up?
Is there a way to solve it?

The region of memory allocated by malloc has an indeterminate initial value.
From the C Standard (emphasis mine):
(c99, 7.20.3.3p2) "The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate*."
Use calloc or memset after malloc to have a determinate value.

Malloc does not implicitly zero out the allocated memory. You need to cell either calloc or memset for this purpose:
heap = malloc(100);
memset(heap, 0, 100);
or
heap = calloc(100, 1);

When you use void free( void* ptr ); to release a previously allocated memory block, you use the pointer variable as an argument to the free function. The function only reads the pointer variable, and does not automatically set it to NULL for you.
Therefore, it is up to you to set that variable to NULL, so that other code you have written, which may depend on that variable, will be dealing with a NULL pointer, instead of a memory address that looks OK but points to memory that cannot be accessed any longer.

When you free any memory block you should always set the pointer variable to NULL, because the memory is no longer accessible.

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;

Initialization of malloc & calloc

Why does malloc always initialize with garbage values and calloc always intialize with 0? Any reason behind it?
Why can't we use realloc instead of malloc for dynamic memory allocation?
After reallocating memory dynamically, what are initial values of it?
Code:
int *ptr;
ptr = (int *) realloc(ptr,50);
printf("%d",*ptr);
malloc is made to just allocate memory of the specified size. calloc does the same (with different parameters), but is also designed to zero initialize the memory. It is just how they are designed.
You can use realloc for dynamic reallocation, but it is used to reallocate, which in your example it is not. realloc can only be used on memory already initialized with malloc, calloc, or realloc, or if the pointer is NULL then it is equivalent to malloc
Why does Malloc always initialize with Garbage values & Calloc always intialize with 0?
This behaviour is defined by the C standard.
In fact malloc() does not initialise the memory allocated at all. This mostly is for performance reasons. Do not read it, before having written to it yourself, to not provoke UB.
calloc() is specified to initialise the memory allocated to all 0s.
why can't we use realloc instead of malloc for dynamic memeory allocation.
You can. Just pass NULL as 1st parameter.
Your example adjusted:
int *ptr = NULL;
ptr = realloc(ptr, 50);
*ptr = 42;
printf("%d\n", *ptr);
prints:
42

How free memory after of realloc

Is correct ways to free up memory in this code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void ){
char *string1, *string2;
string1 = (char*) malloc(16);
strcpy(string1, "0123456789AB");
string2 = realloc(string1, 8);
printf("string1 Valor: %p [%s]\n", string1, string1);
printf("string2 Valor: %p [%s]\n", string2, string2);
free(string1);
free(string2);
return 0;
}
Since the two pointers point to the same direction
I think your confusion comes from the (uninspired) expression "free pointers" (you used in your post, but edited it out since). You don't free pointers. You free memory. The pointer is just telling which memory.
In your example you have: the memory obtained from malloc. string1 points to this memory. Then when you call realloc a new memory block is obtained (possibly starting at the same address, possibly not), but realloc takes care to release the old one if needed (and is therefore undefined behavior to access or free it yourself). string2 points to this new memory block.
So you have to free just the memory block obtained from realloc. string2 points to that memory.
In short, no.
Per the C Standard:
7.22.3.5 The realloc function
...
The realloc function deallocates the old object pointed to
by ptr and returns a pointer to a new object that has the
size specified by size. The contents of the new object shall
be the same as that of the old object prior to deallocation, up to the
lesser of the new and old sizes. Any bytes in the new object beyond
the size of the old object have indeterminate values.
Once you call realloc(), you do not have to free() the memory addressed by pointer passed to realloc() - you have to free() the memory addressed by the pointer realloc() returns. (Unless realloc() returns NULL, in which case the original block of memory - passed to realloc() - has to be free()'d.)
When you call realloc, either the returned pointer is the same as the original, or a new pointer is returned and the original pointer becomes invalid. In the first case, calling free on both string1 and string2 results in a double-free since the pointers are equal. In the second case, calling free on string1 is a double-free since it was already freed.
So either way you have a double-free which results in undefined behavior.
From the man page for realloc:
void *realloc(void *ptr, size_t size);
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range
from the start of the region up to the minimum of the old and new
sizes. If the new size is larger than the old size, the added memory
will not be initialized. If ptr is NULL, then the call is equivalent
to malloc(size), for all values of size; if size is equal to zero, and
ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr
is NULL, it must have been returned by an earlier call to malloc(),
calloc() or realloc(). If the area pointed to was moved, a free(ptr)
is done.
The realloc() function returns a pointer to the newly allocated
memory, which is suitably aligned for any kind of variable and may be
different from ptr, or NULL if the request fails.
Also from the man page for free:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
You only need to free(string2).
Short answer: in your code, calling free(string2) is correct, and sufficient. Calling free(string1) is incorrect.
When you called realloc (and assuming that the call succeeded), its return value (which you stored in string2) became the one and only way to refer to the one block of memory that you have.
It may be that realloc resized your memory block "in place", meaning that the values of string2 and string1 are equal. In that case, calling free(string1) is wrong because you're freeing the same pointer twice.
It may be that realloc moved your data to a new place in the process of resizing it. In that case, the values of string2 and string1 are unequal. But in that case, after it finds a new place for your data and copies it there, realloc automatically frees the old block for you. So, again, calling free(string1) is wrong because you're freeing an already-freed pointer.
Think of realloc as something equivalent to:
void *
realloc(void *old, size_t new_size)
{
size_t old_size = magic_internal_function_that_knows_the_size_of(old);
void *new = malloc(new_size);
if (new == NULL)
return NULL;
memcpy(new, old, new_size > old_size ? old_size : new_size);
free(old);
return new;
}
If you have the magic function that can figure out how big an allocation is from the pointer, you can implement realloc yourself like this. malloc pretty much must have this function internally for free to work.
realloc can also do clever things like figuring out that you're reallocating to a smaller size and just free part of your allocation or figure out that you're growing your allocation and there's enough space after to fit it. But you don't need to think about those cases. Thinking that realloc is malloc+memcpy+free will not mislead you except that you need to remember that realloc failing and returning NULL means it didn't do the free.
The realloc implicity frees the input, it may not do anything at all, but you cannot free it after to re-alloced memory. So
char *string1, *string2;
string1 = (char*) malloc(16);
....
string2 = realloc(string1, 8); // this line implicitly frees string1
free(string1); // this is wrong !!!
free(string2);

dynamic memory allocation in c , free some part of memory that is allocated before using malloc()

Is there any way to free some part of memory you created by using malloc();
suppose:-
int *temp;
temp = ( int *) malloc ( 10 * sizeof(int));
free(temp);
free() will release all 20 byte of memory but suppose i only need 10 bytes. Can i free last 10 bytes.
You should use the standard library function realloc. As the name suggests, it reallocates a block of memory. Its prototype is (contained in the header stdlib.h)
void *realloc(void *ptr, size_t size);
The function changes the size of the memory block pointed to by ptr to size bytes. This memory block must have been allocated by a malloc, realloc or calloc call. It is important to note that realloc may extend the older block to size bytes, may keep the same block and free the extra bytes, or may allocate an entirely new block of memory, copy the content from the older block to the newer block, and then free the older block.
realloc returns a pointer to the block of reallocated memory. If it fails to reallocate memory, then it returns NULL and the original block of memory is left untouched. Therefore, you should store the value of ptr in a temp variable before calling realloc else original memory block will be lost and cause memory leak. Also, you should not cast the result of malloc - Do I cast the result of malloc?
// allocate memory for 10 integers
int *arr = malloc(10 * sizeof *arr);
// check arr for NULL in case malloc fails
// save the value of arr in temp in case
// realloc fails
int *temp = arr;
// realloc may keep the same block of memory
// and free the memory for the extra 5 elements
// or may allocate a new block for 5 elements,
// copy the first five elements from the older block to the
// newer block and then free the older block
arr = realloc(arr, 5 * sizeof *arr);
if(arr == NULL) {
// realloc failed
arr = temp;
}
You can use realloc function provided by the standard c library.
C99 Standard 7.20.3.4-1: The realloc function:
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.

In C - freeing memory in different contexts

If you were to do something like:
char array[2][5] = {"cars", "tags"}
char array2[] = "computer";
There has been an implicit allocation of memory allocated equal to(for the first line):
sizeof(array); OR
sizeof(char*10);
Or however you want to do it.
Alternatively, one could do this:
char *ptr = "cars";
char *ptr2 = malloc(sizeof(*ptr2)*5);
*ptr2 = "cars";
I know that if you are using pointers to explicitely allocate memory using malloc then it is good practice to free that pointer using free(ptr);
However, when you define things as above, are the following calls necessary on the same grounds as the explicit allocation of memory?
free(ptr);
free(ptr2);
free(array);
free(array2);
-- As an aside, all of the above delcarations/initializations are implicitely NULL-terminated strings, right?
You only need to free memory allocated with malloc, the other cases you specified are pointers to string literals or automatic variables(usually allocated on the stack) attempting to free them is undefined behavior.
C style strings are NULL terminated.
Also, important to note that:
*ptr2 = "cars";
is not correct syntax.
You should only ever call free when passing something allocated with a call to malloc. Which means that you should only ever call free with ptr2.
Furthermore, your assignment *ptr2 = "cars" is a syntax error. You would need to use strcpy to fill ptr2. Like this:
char *ptr2 = malloc(sizeof(*ptr2)*5);
strcpy(ptr2, "cars");
C strings are null-terminated by convention, and string literals, i.e. "cars" are null-terminated.
However, when you define things as above, are the following calls necessary on the same grounds as the explicit allocation of memory?
No, its illegal to free memory which are not returned by malloc or calloc or realloc.
all of the above delcarations/initializations are implicitely NULL-terminated strings, right?
Yes, those strings are called string literals and will be NULL termintaed.
*ptr2 = "cars"; is not a valid statement. If you want to point ptr2 someplace else, you need to use:
ptr2 = "cars";
If you want to overwrite the memory ptr2 points to, use strcpy:
strcpy(ptr2, "cars");
Only ptr2 needs to be freed - it's the only one you allocated with malloc. Note that if you make the ptr2 = "cars" assignment mentioned above, you won't be able to free the original memory you allocated. That's a logical error known as a "memory leak".
You only have to free memory yo have allocated using malloc, when you declare a static array memory is freed automatically at the end of the code block.

Resources