how can i control that free() function works fine? - c

i have a little question in relation to the free() function of C.
I allocate in a program a multidimensional array with this code :
char **newMatrix( int N ){
int i,j;
char **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * N);
}
}
at the end of the program the array is full of characters.
So i do this to deallocate the memory.
void freeArray(char **a, int m){
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
My question is , how can I really check if the free() function works well , and deallocate all the memory?
I ask you because I have tried to print the matrix after the freeArray , and the result is that the values are still stored in the a[i][j] columns and rows .
Sorry if it will be a stupid question , i'm new of C programming!

free does not mean that it will actually delete the memory! It will inform to the OS that I don't want this memory any more, use it for some other process!
You can certainly continue to use array a after calling free(a) and nothing will stop you. However the results will be completely undefined and unpredictable. It works by luck only. This is a common programming error called "use after free" which works in many programs for literally years without "problems" -- until it causes a problem.
There are tools which are quite good at finding such errors, such as Valgrind.

free will not clear the memory for you. It just marks it as available for the OS to reallocate somewhere else. People tend to assign NULL to a pointer after freeing to prevent accidental reuse. If you want to be sure what your code is doing, you could memset the allocated space to a known value before freeing. To be honest, just print out how much data you mallocate and make sure you free the same size of data from the same pointer.

free() will only remove the reference to memory pointed to, by the pointer passed to it.
Once a pointer is passed to free() and the free() returns a success(which always is..), the pointer should never be used.
To avoid this usage, which is a illegal reference, a pointer variable should always be assigned NULL after it is passed to free().

If I understood you correctly you want to check if:
You don't reuse memory after freeing it
You freed all of the memory
It's not possible to do it directly from within language - however there are tools which can help. For example Valgrind can check both of those things (and much more). If you are on Windows tools like UMHD can be helpful but I haven't found any freeware replacement (though see also "Is there a good Valgrind substitute for Windows?" question)

Related

Freeing dynamically allocated 2D array in C

I have this code segment:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int ** ar;
int i;
ar = malloc( 2 * sizeof(int*));
for(i=0; i<2; i++)
ar[i] = malloc ( 3 * sizeof(int) );
ar[0][0]=1;
ar[0][1]=2;
ar[0][2]=5;
ar[1][0]=3;
ar[1][1]=4;
ar[1][2]=6;
for(i=0; i<2; i++)
free(ar[i]);
free(ar);
printf("%d" , ar[1][2]);
return 0;
}
I went through some threads on this topic
(how to free c 2d array)
but they are quite old and no one is active.
I had the following queries with respect to the code:
Is this the correct way to free memory for a 2D array in C?
If this is the correct way then why am I still getting the corresponding array value when I try to print ? Does this mean that memory is not getting freed properly ?
What happens to the memory when it gets freed? Do all values which I have stored get erased or they just stay there in the memory which is waiting for reallocation?
Is this undefined behaviour expected?
Yes you have two levels or layers (so to speak) of memory to free.
The inner memory allocations (I like how you do those first)
The outer memory allocation for the topmost int** pointer.
Even after you freed the memory, nothing was done with it to overwrite it (So yes it's expected). Hence why you can still print them to the console. It's a good idea to always NULL your pointers after you are done with them. Kind of the polite thing to do. I've fixed many bugs and crashes in the past because the code did not null the pointers after freeing them.
In Microsofts Visual Studio, with the Debug C runtime, it can overwrite the newly free'd values with some garbage that will immediately raise an access violation if used, or dereferenced. That's useful for flushing out bugs.
It looks like you are new to C (Student?). Welcome and have a fun time.

How do you free a 2D malloc'd array in C?

I'm creating a 2D Array in C; am I freeing it correctly?
// create
int n = 3;
int (*X)[n] = malloc(sizeof(int[n][n]));
// set to 0
for(int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
X[i][j] = 0;
}
}
// is this all I need?
free(X);
You must call free once for each malloc. Your code has one malloc and one free (with the same address) so it is correct.
For every malloc(), there must be a matching free(). So if you call malloc() in a loop, there must be a similar loop later on that calls free() just as many times. Your code has one malloc() and one corresponding free(), so yes, you have freed everything you need to.
The most common way I've seen to allocate a two-dimensional array is to do something like:
int **arr = malloc(sizeof (int *) * num_rows);
for (i = 0; i < num_rows; ++i)
arr[i] = malloc(sizeof (int) * num_cols);
/*
* Using `sizeof *arr` and `sizeof **arr`
* respectively would have been more safe,
* but for the purpose of this example, I think
* using `int *` and `int` is simpler to
* understand.
*/
then later to free:
for (i = 0; i < num_rows; ++i)
free(arr[i]);
free(arr);
This makes the outer dimension hold num_row pointers to pointers to int (each of the num_row pointers points to the starting address of the 'column'). So each element in the outer dimension points to a row, and in each row there are num_cols elements in the inner dimension (the 'columns'), which is just a group of num_cols integers. Does this make sense to you? So you have to allocate num_rows integer pointers, and each one of these points to the first 'column' of that row--for each row you have to allocate space for num_cols integers, so you can see the loop will make a total of num_rows * num cols integers, and they way they are allocated allows you to use array indexing notation (two-dimensional in this case--each element in the outer dimension points to the start of a 'row', which contains a pointer to the start of a 'column', hence the double pointer) to access the elements. I know this is probably confusing, that is why I tried to describe it so many different times/ways, but please just ask any questions, especially about what you don't understand in particular, and I will be more than happy to work with you in helping understand it.
I'm not saying you have to create your 2-D array this way; your way works fine too, I just wanted to show you this way since you are likely to run into it since it's very common.
Also, look into Valgrind. You can use that tool to see if you have forgotten any free()s / have an unmatched malloc(), and lets you know if there is any allocated memory unreachable/leaked (maybe the pointer was changed before the call to free() so the call doesn't properly free the memory and you get a leak).
RastaJedi - another couple of things to note:
After a call to free(), it's a good idea to set the free'd variable to NULL, which helps prevent use after free.
Also, if you malloc in one block of code, then free in some called function, and then return from that function, sometimes C forgets about the final free (in your example, free(arr) ), and you should set the variable to NULL upon return.
I came here, and verified that the malloc and free calls that I wrote in the code I'm working on are indeed exactly as your "common" way, but kept running into a Seg Fault, because I was using malloc from in main, free-ing from a helper function which received the double-indirect head of the array. Having that all wrapped in a while-loop for user interaction, a second pass around was checking the array head for NULL-ness, but not seeing it as NULL, despite explicitly setting to NULL inside the helper function. Crawling thru the code with a debugger is how I identified the behavior, and why I came looking.
After being free'd, the memory is available, and variously (and randomly) reassigned; when the function with the free() calls returns, the memory that was allocated has been released, however it seems that the calling code still holds a pointer to that place in memory. There then exists a possible race-condition; by the time the calling code regains control, there's no guarantee as regards the location pointed to by the variable used for the array head, and therefore it's a very good idea to set the variable to NULL after the function returns.
Although you can use malloc'd pointers for pass-by-reference behavior, after a call to free() inside some function, the by-reference behavior breaks (because the thing being referenced is what has been free'd).
So, thank you for your answer, which confirmed that I was looking at the wrong part of my problem - just figured maybe someone else may stumble here, and possibly have the same issue I did.

Free Dynamically Allocated Array C

I am in a bit of dilemma, thus, first of all I would like to apologize of if the next questions will be a bit more noobish or if they have been asked before (I couldn't find the answers for those though).
Anyway, I will explain it by giving a task as an example (it's not homework, it's just for the sake of my question). Here it goes:
Given a string from stdin index each word, then print each word on one line.
Example:
str[] = "Stack is awesome"
str_index {
[0] => "Stack"
[1] => "is"
[2] => "awesome"
}
I know that there are many ways to solve this, but, again, for the sake of my question
Bare this solution:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* fgets adds an unwanted '\n' at the end, so I made
* a special function to read from stdin that removes
* that '\n'.
*/
int read(char *str, int size) {
// fgets adds an unwanted '\n' at the end, so we remove it
fgets(str, size, stdin);
int length = strlen(str);
str[length - 1] = '\0';
return length;
}
/* A function that breaks a string into words, indexes them
* and prints them out, all done dynamically with malloc.
*/
void str_index(char *str) {
char **index, *ptr;
int i = 0, number_of_words;
index = malloc(sizeof(char *));
ptr = strtok(str, " ");
for(i = 0; ptr != NULL; i++) {
index = realloc(index, (i + 1) * sizeof(char *));
index[i] = malloc(50 * sizeof(char));
strcpy(index[i], ptr);
ptr = strtok(NULL, " ");
}
number_of_words = i;
for(i = 0; i < number_of_words; i++) {
printf("%s\n", index[i]);
}
return;
}
int main() {
char str[250];
read(str, 250);
str_index(str);
return 0;
}
QUESTIONS
Where do I have to free the arrays that I have allocated dynamically
in str_index?
Do we have to free them within the function str_index? If so, why?
What I know is that when a function is done executing all local
variables are destroyed.
Why do we have to free them in main? Isn't main a function aswell,
thus upon finishing executing it all variables defined in that function are destroyed.
I'm guessing you are doing a university course. The problem (in my opinion) with university courses is that they start by teaching high level languages where everything is done magically, and then teach you a low level language. If I ruled the world, everyone would start with assembler, then C, then be allowed to 'progress' to Java etc.
To your question, the problem you have is the assumption that 'things might be done magically'. C doesn't do very much magically at all. In particular, if you malloc() or calloc() anything, or allocate anything using something that uses the heap allocator (for instance strdup()), it's your responsibility to free it. And you will need to do that explicitly. If you don't, you will have a memory leak. The first order problem is thus 'if I allocated it, I must ensure it is freed'. The second order problem is 'if I used a library that might have allocated stuff, I need to work out how to ensure it knows I've done, so it can free stuff'. If you bear this in mind, your C programming life will be happy, and valgrind will be your friend.
Let's now consider your questions:
You ask where you should free your dynamically allocated memory. Technically, in this example, you don't need to, because exiting your program will free all memory on the heap. However, let's suppose you want to use this function repeatedly. You want to free the allocation as soon as you no longer have a use for it. In the example presented, that would be immediately before the return. If you had other exits from the function, then make sure you free your allocation before every return. A useful error handling hint is to exit via the same code, and whenever you free() the allocation, also set the pointer to the allocation to NULL. On entry, also initialise the pointer to NULL. Then on exit (a valid use of goto), you can simply check the pointer against NULL, and if it is not null, free() it. (In fact once you get really cocky, you will know free() on NULL on most platforms is a no-op, so you can unconditionally free it). The setting the pointer to NULL bit is to avoid a double free.
This is the difference between the stack and the heap. Local variables are allocated on the stack. C destroys them automatically when a function returns. This is one of the few bits of magic C does. Note that I said it destroys the variables, not the things they point to. So if you have a pointer to allocated (heap) memory in a local variable, and the function returns, it will 'free' the variable (in the sense it will no longer be on the stack), but the allocated (heap) memory will not be freed. This is why you must free heap allocated memory only referenced in a function before the pointers to it are destroyed by exiting the function - see the answer to 1 above.
You don't need to free anything in main() in your example. If you had coded your function to return a pointer to memory on the heap (for instance if you'd coded the equivalent of strdup()) then your main() function would need to free() that. That brings up the important point that what the caller needs to free() depends on how the called function is designed. It's thus important that the called function makes this obvious in documentation.
Where do I have to free the arrays that I have allocated dynamically in str_index?
Just before the return; statement of your function str_index.
Do we have to free them within the function str_index?
Not necessary. Depends on the program requirement.
What I know is that when a function is done executing all local variables are destroyed.
Yes, it is true for space allocated on stack (if variable is not static), but not for the space allocated on heap.
Why do we have to free them in main?
Not necessary that it have to free in main. Depends on the program requirement.

How to prevent dangling pointers/junk in c?

I'm new to C and haven't really grasped when C decides to free an object and when it decides to keep an object.
heap_t is pointer to a struct heap.
heap_t create_heap(){
heap_t h_t = (heap_t)malloc(sizeof(heap));
h_t->it = 0;
h_t->len = 10;
h_t->arr = (token_t)calloc(10, sizeof(token));
//call below a couple of times to fill up arr
app_heap(h_t, ENUM, "enum", 1);
return h_t;
}
putting h_t through
int app_heap(heap_t h, enum symbol s, char* word, int line){
int it = h->it;
int len = h->len;
if (it + 1 < len ){
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
h->arr[it].word = word;
h->arr[it].line = line;
h->it = it + 1;
printf(h->arr[it].word);
return 1;
} else {
h->len = len*2;
h->arr = realloc(h->arr, len*2);
return app_heap(h, s, word, line);
}
}
Why does my h_t->arr fill up with junk and eventually I get a segmentation fault? How do I fix this? Any C coding tips/styles to avoid stuff like this?
First, to answer your question about the crash, I think the reason you are getting segmentation fault is that you fail to multiply len by sizeof(token) in the call to realloc. You end up writing past the end of the block that has been allocated, eventually triggering a segfault.
As far as "deciding to free an object and when [...] to keep an object" goes, C does not decide any of it for you: it simply does it when you tell it to by calling free, without asking you any further questions. This "obedience" ends up costing you sometimes, because you can accidentally free something you still need. It is a good idea to NULL out the pointer, to improve your chance of catching the issue faster (unfortunately, this is not enough to eliminate the problem altogether, because of shared pointers).
free(h->arr);
h -> arr = NULL; // Doing this is a good practice
To summarize, managing memory in C is a tedious task that requires a lot of thinking and discipline. You need to check the result of every allocation call to see if it has failed, and perform many auxiliary tasks when it does.
C does not "decide" anything, if you have allocated something yourself with an explicit call to e.g. malloc(), it will stay allocated until you free() it (or until the program terminates, typically).
I think this:
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
/* more accesses */
is very weird, the first two lines don't do anything sensible.
As pointed out by dasblinkenlight, you're failing to scale the re-allocation into bytes, which will cause dramatic shrinkage of the array when it tries to grow, and corrupt it totally.
You shouldn't cast the return values of malloc() and realloc(), in C.
Remember that realloc() might fail, in which case you will lose your pointer if you overwrite it like you do.
Lots of repetition in your code, i.e. realloc(h->arr, len*2) instead of realloc(h->arr, h->len * sizeof *h->arr) and so on.
Note how the last bullet point also fixes the realloc() scaling bug mentioned above.
You're not reallocating to the proper size, the realloc statement needs to be:
realloc(h->arr, sizeof(token) * len*2);
^^^^^^^^^^^^
(Or perhaps better realloc(h->arr, sizeof *h->arr * h->h_len);)
In C, you are responsible to free the memory you allocate. You have to free() the memory you've malloc/calloc/realloc'ed when it's suitable to do so. The C runtime never frees anything, except when the program has terminated(some more esoteric systems might not release the memory even then).
Also, try to be consistent, the general form for allocating is always T *foo = malloc(sizeof *foo), and dont duplicate stuff.
e.g.
h_t->arr = (token_t)calloc(10, sizeof(token));
^^^^^^^^ ^^ ^^^^^^^^^^^^^
Don't cast the return value of malloc in C. It's unncessesary and might hide a serious compiler warning and bug if you forget to include stdlib.h
the cast is token_t but the sizeof applies to token, why are they different, and are they the same type as *h_t->arr ?
You already have the magic 10 value, use h_t->len
If you ever change the type of h_t->arr, you have to remember to change the sizeof(..)
So make this
h_t->arr = calloc(h_t->len, sizeof *h_t->arr);
Two main problems in creating dangling pointers in C are the not assigning
NULL to a pointer after freeing its allocated memory, and shared pointers.
There is a solution to the first problem, of automatically nulling out the pointer.
void SaferFree(void *AFree[])
{
free(AFree[0]);
AFree[0] = NULL;
}
The caller, instead calling
free(p);
will call
SaferFree(&p);
In respect to the second and harder to be siolved issue:
The rule of three says:
If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.
Sharing a pointer in C is simply copying it (copy assignment). It means that using the rule of three (or the general rule of 0)
when programming in C obliges the programmer to supply a way to construct and especially destruct such an assignment, which is possible, but not an
easy task especially when C does not supply a descructor that is implicitly activated as in C++.

Why do I get different results when I dereference a pointer after freeing it?

I've a question about the memory management in C (and GCC 4.3.3 under Debian GNU/Linux).
According to the C Programming Language Book by K&R, (chap. 7.8.5), when I free a pointer and then dereference it, is an error. But I've some doubts since I've noted that sometimes, as in the source I've pasted below, the compiler (?) seems to work according a well-defined principle.
I've a trivial program like this, that shows how to return an array dynamically allocated:
#include <stdio.h>
#include <stdlib.h>
int * ret_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i*2;
}
printf("Address pointer in ret_array: %p\n", (void *) arr);
return arr;
}
int * ret_oth_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i+n;
}
printf("Address pointer in ret_oth_array: %p\n", (void *) arr);
return arr;
}
int main(void)
{
int *p = NULL;
int *x = NULL;
p = ret_array(5);
x = ret_oth_array(6);
printf("Address contained in p: %p\nValue of *p: %d\n", (void *) p, *p);
free(x);
free(p);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
If I try to compile it with some arguments: -ansi -Wall -pedantic-errors, it doesn't raises errors or warning. Not only; it also runs fine.
Address pointer in ret_array: 0x8269008
Address pointer in ret_oth_array: 0x8269038
Address contained in p: 0x8269008
Value of *p: 0
Memory freed.
*p+4 = 8
*x = 0
*(p+4) is 8 and *x is 0.
Why does this happen?
If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
Another strange thing happens if I try to change the order of the calls to free.
E.g.:
int main(int argc, char * argv[])
{
/* ... code ... */
free(p);
free(x);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
In fact in this case the output (on my machine) will be:
*p+4 = 8
*x = 142106624
Why does the x pointer is really "freed", while the p pointer is freed (I hope) "differently"?
Ok, I know that after freeing memory I should make the pointers to point to NULL, but I was just curious :P
It is undefined behaviour, so it is an error to deference freed pointer as strange things may (and will) happen.
free() doesn't change the value of the pointer so it keeps pointing to the heap in the process address space - that's why you don't get segfault, however it is not specified and in theory on some platforms you can get segfault when you try to dereference pointer immediately after freeing.
To prevent this it is a good habit to assign pointer to NULL after freeing so it will fail in predictable way - segfault.
Please note that on some OSes (HP-UX, may be some others as well) it is allowed to dereference NULL pointer, just to prevent segfault (and thus hiding problems). I find it rather stupid as it makes things much more difficult to diagnose, although I don't know the full story behind this.
free() (and malloc()) are not from gcc. They come from the C library, which on Debian is usually glibc. So, what you are seeing is glibc's behavior, not gcc's (and would change with a different C library, or a different version of the C library).
I particular, after you use free() you are releasing the memory block malloc() gave you. It's not yours anymore. Since it is not supposed to be used anymore, the memory manager within glibc is free to do whatever it wants with the memory block, including using parts of it as its own memory structures (which is probably why you are seeing its contents change; they have been overwritten with bookkeeping information, probaly pointers to other blocks or counters of some sort).
There are other things that can happen; in particular, if the size of your allocation was large enough, glibc can ask the kernel for a separate memory block for it (with mmap() or similar calls), and release it back to the kernel during the free(). In that case, your program would crash. This can in theory also happen in some circunstances even with small allocations (glibc can grow/shrink the heap).
This is probably not the answer you are looking for, but I'll give it a try anyway:
Since you're playing with undefined behaviour that you should never depend on in any way, shape or form, what good does it do to know how exactly one given implementation handles that?
Since gcc is free to change that handling at any given time, between versions, architectures or depending on the position and brightness of the moon, there's no use whatsoever in knowing how it handles it right now. At least not to the developer that uses gcc.
*(p+4) is 8 and *x is 0. Why does this happen? If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
One possible explanation for this would be that printf("...%i..."...) might internally use malloc to allocate a temporary buffer for it's string interpolation. That would overwrite the contents of both arrays after the first output.
Generally, I would consider it an error if a program relies on the value of a pointer after it has been freed. I would even say that it's a very bad code smell if it keeps the value of a pointer after it has been freed (instead of letting it go out of scope or overwriting it with NULL). Even if it works under very special circumstances (single-threaded code with a specific heap manager).
Once you free the dynamic-memory variable, it is not yours. The memory manager is free to do what ever it sees better with that piece of memory you where pointing to. The compiler doesn't do anything as far as I know with the freed blocks of memory, because it is a function and not defined by the language. Even if it is defined by the languages, the compiler just inserts calls to the underlying OS functions.
Just wanna say, It is undefined by the language, So you have to check your OS and watch that piece of memory after freeing it. The behavior maybe random, because sometimes other programs ask for memory, sometimes not!
by the way, It is different on my machine, the value changes for both pointers.
Although the behavior you're seeing seems to be consistent, it is not guaranteed to be so. Unforeseen circumstances may causes this behavior to change (let alone the fact that this is completely implemetnatation dependent).
Specifically, in your example you free() the array and then get the old content when you access the array. If you'll have additional malloc() calls after the free() - chances are that the old contents will be lost.
Even if the memory is freed, it is not necessarily reused for some other purpose. Old pointers to your process memory are still valid pointers (though to unallocated memory) so you do not get segmentation faults either.

Resources