Trying to understand behavior when freeing allocated memory - c

I have code that functions like this:
void** array;
array = malloc(8*sizeof(void*));
And if I put, say, three elements into the array and try:
int i = 0;
for(i; i < 8; i++)
free(array[i]);
It fails after 6 iterations of the loop. But if I populate the entire array (with 8 elements), the for loop executes just fine. I've tried this with 18 as well, and the loop fails after 9 iterations, but if I populate the whole thing it executes fine.
Can someone please explain what's happening here?

The memory returned by malloc is not initialized; it may contain garbage data. You're allocating an array of pointers, but its initial contents are not valid pointers. You're setting some of the items to (presumably) valid pointers, but leaving others uninitialized, and then you call free on all the items — even the uninitialized garbage ones.
You need to either:
keep track of which items in the array have been set to a valid pointer, and call free only on those items, or
explicitly initialize all the items to NULL. This makes it safe to free them all, since free(NULL) is valid (and does nothing).

Memory allocated for and assigned to pointer to pointer is of type pointer so as to assign further memory for the inner pointers to hold the actual data i.e int** is assigned with memory of int* so that ints can be assigned to the allocated int*:
// array is a double pointer variable
void **array = malloc(8 * sizeof *array); // (1) allocate memory for 8 void* pointers
for (int i = 0; i < 8; ++i)
array[i] = malloc(sizeof(int));
// (2) - malloc for the actual data to be pointed by the above allocated pointers
then you've to do this for freeing the memory
for (int i = 0; i < 8; ++i)
free(array[i]); // undo (2)
free(array); // undo (1)
You've to match every malloc with a free. Since you've done only 1, you should undo only 1.

Related

Segmentation Fault (SIGSEGV) when using malloc on null pointer

This is what my main functions looks like. This cannot be changed as it is being used in the file my professor is using to grade the assignment.
char** lines = NULL;
int line_count = 5;
add_lines(&lines, line_count);
In this function, I need to dynamically allocate the lines array and store multiple strings inside. The memory is then being freed in main. This is how I am currently doing it, but I keep getting a segfault. (This function also must take a char***).
void add_lines(char*** lines, int line_count) {
*lines = (char**)malloc(line_count*sizeof(char*));
for (int i = 0; i < line_count; i++)
*lines[i] = (char*)malloc(64*sizeof(char));
}
I am assuming this error has to do with dereferencing and trying to dynamically allocate a NULL pointer, but I'm not sure how I'd go about fixing it.
This line isn't doing what you think:
*lines[i] = (char*)malloc(64*sizeof(char));
The array index operator [] has higher precedence than the unary dereference operator *. So it attempts to access lines as an array (which it isn't), then dereference the array member. This ends up working when i is 0 because it will point to the first allocated array element, but when i is larger you access memory past lines in the calling function.
You need to use parenthesis to make sure you dereference lines first, then index the array elements.
(*lines)[i] = malloc(64*sizeof(char));
Also, don't cast the return value of malloc. It's unnecessary and can mask subtle bugs.

Dynamically allocated 2 dimensional arrays

Does anyone know what the third line "Free(array)" does? array here is just the address of the first element of array(in other words, a pointer to the first element in the array of int * right)? Why do we need the third line to free the "columns" of the 2D array? I basically memorized/understand that a is a pointer to means a holds the address of ____. Is this phrase correct?
For example: int **a; int * b; int c; b = &c = 4;
a = &b; This is correct right? Thankyou!!!
Also, in general, double pointers are basically dynamically allocated arrays right?
"Finally, when it comes time to free one of these dynamically allocated multidimensional ``arrays,'' we must remember to free each of the chunks of memory that we've allocated. (Just freeing the top-level pointer, array, wouldn't cut it; if we did, all the second-level pointers would be lost but not freed, and would waste memory.) Here's what the code might look like:" http://www.eskimo.com/~scs/cclass/int/sx9b.html
for(i = 0; i < nrows; i++)
free(array[i]);
free(array);
Why do we need the third line to free the "columns" of the 2D array?
The number of deallocations should match up with the number of allocations.
If you look at the code at the start of the document:
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++) {
array[i] = malloc(ncolumns * sizeof(int));
}
you'll see that there is one malloc() for the array itself and one malloc() for each row.
The code that frees this is basically the same in reverse.
Also, in general, double pointers are basically dynamically allocated arrays right?
Not necessarily. Dynamically allocated arrays is one use for double pointers, but it's far from the only use.
Calls to malloc allocate memory on the heap, equal to the number of bytes specified by its argument, and returns the address of this block of memory. Your '2D array' is really a 1D array of int addresses, each pointing to a chunk of memory allocated by malloc. You need to free each of these chunks when you are done, making it available for others to use. But your 1D array is really just another malloc'd chunk of memory to hold these malloc'd addresses, and that needs to be freed also.
Also, when you use printf("%s", array) where array is an char *, the compiler sees the array as the address of array[0] but prints it right? I'm just curious if I'm understanding it right.
Yes, %s tells printf to go to whatever address you give it (an address of a char, aka a char*, let's say), and start reading and displaying whatever is in memory at that address, one character at a time until it finds a 'NULL character'. So in the case of a string, that is the expected behavior, since a string is just an array of chars, followed by the '\0' char.

Allocating memory for one dimensional array in 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.

How is initializing an array different from mallocing memory?

I am new to C++. I am having trouble differentiating between initializing an array and mallocing memory. To me, they seem to accomplish the same purpose.
Specifically, I can initialize an array via int myArray[] = {1, 2, 3};. I can also use malloc to obtain memory and assign it to a void pointer. Later, I free this memory.
What is the difference between these two methods? Does a computer store the data in the same places and in the same ways?
In C++ there are two different ways you can allocate memory. The first way allocates memory on the stack.
int arr[] = {1,2,3};
int arr[3];
Both of these lines of code create an array of size 3 on the stack. The only difference is the first line also initializes the values in the array.
The second way you can allocate memory is on the heap. The amount of memory available on the heap is usually much larger than is available on the stack. The new and malloc operations allocate memory on the heap.
int* arr = (int*) malloc(100*sizeof(int));
int* arr = new int[100];
Both of these lines of code create an array of size 100 on the heap. Now here's the difference between the two. In C++ you should always use new because it ensures that the constructors for each element in your array are called. It is also much more type safe, unlike malloc which isn't type safe at all since it just returns a void* to a chunk of bytes that can be interpreted anyway you'd please.
Now if you're dynamically allocating memory, meaning you don't know the size of the array until runtime, you should always allocate it on the heap using new/malloc.
Last thing to note is how you free your memory, using delete/free.
free(arr); //arr was allocated with malloc
delete[] arr; //arr was allocated with new
If you allocated memory with new it must be freed with delete. You can't mix and match new/malloc with delete/free. Lastly delete[] frees an array of objects. If you only allocated a single object then you just use delete.
Object* myobj = new Object;
delete myobj;
In my opinion, this question does not belong to here. But I will answer it. You can do that with:
int* myArray = (int *) malloc(3 * sizeof(int));
This means that you are creating memory location with memory size 3 * sizeof(int) [i.e. the size of the integer data type in C], and you re returning an int pointer to this memory location. [i.e. a pointer that points to the beginning of it, and deal with it as it if contains integers]. These memory slots are converted to int * (using (int *)), and called myArray. myArray is an int array (and an int pointer). Because arrays are actually pointers in C. Then you do:
for (int i = 0; i < 3; i++)
myArray[i] = i + 1;
There could be some issues in malloc. Therefore, after the initialization always check if myArray == NULL. If this is case, fix the error, and dont initialize the array with $\{1,2,3\}$. Otherwise, you will get a segmentation fault.
I wish I am not vague to you. But since you are using C++, I would suggest you use the new operator instead. you would do:
int myArray[] = new int[3];

How to get the size of dynamically allocated 2d array

I have dynamically allocated 2D array.
Here is the code
int **arrofptr ;
arrofptr = (int **)malloc(sizeof(int *) * 2);
arrofptr[0] = (int *)malloc(sizeof(int)*6144);
arrofptr[1] = (int *)malloc(sizeof(int)*4800);
Now i have to know that how many bytes are allocated in arrofptr,arrofptr[0],arrofptr[1]?
is there any way to know the size?
if we will print
sizeof(arrofptr);
sizeof(arrofptr[0]);
sizeof(arrofptr[1]);
then it will print 4.
You can't find size of arrofptr, because it is only a pointer to pointer. You are defining an array of arrays using that. There's no way to tell the size information with only a pointer, you need to maintain the size information yourself.
The only return value you get from malloc() is a pointer to the first byte of the allocated region (or NULL on failure). There is no portable, standard, way of getting the associated allocation size from such a pointer, so in general the answer is no.
The C way is to represent arrays and buffers in general with a pair of values: a base address and a size. The latter is typically of the type size_t, the same as the argument to malloc(), by the way.
if you want to keep track of the size of an allocated block of code you would need to store that information in the memory block that you allocate e.g.
// allocate 1000 ints plus one int to store size
int* p = malloc(1000*sizeof(int) + sizeof(int));
*p = (int)(1000*sizeof(int));
p += sizeof(int);
...
void foo(int *p)
{
if (p)
{
--p;
printf( "p size is %d bytes", *p );
}
}
alt. put in a struct
struct
{
int size;
int *array;
} s;
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the pointer, and thus your calculation the size of the pointers is usually 4, this is why you got 4 and is likely to have the trivial result of 4, always.

Resources