Should I Use Free() In This Case?


Alex.

Retired
Joined
Aug 24, 2005
Messages
4,616
When I have something like char* test = malloc(1000), I call free(test) at the end of the program. However, what if I have:

Code:
unsigned char data1[] = {blah blah blah};
unsigned char data2[] = {blah blah blah blah};
unsigned char data3[] = {blah bla};

unsigned char* dataIndex[] = {data1, data2, data3};
After I'm done with everything, should I call free(datIndex)? or free(dataIndex[n])? My gut says I shouldn't do either, but I'd hate to have memory leaks :-\

Finally, what about char* text = "Hello world" - should I call free(text)? Again I myself think I shouldn't, because I didn't dynamically allocate any memory, but I'm having doubts. All C books I have refer to pointers either by address or by malloc(), so I'm left with this bit of confusion.

Thanks

- Alex
 
You should only free things you allocate yourself, usually with malloc, but sometimes other functions which internally call malloc for you. A simple pointer assignment is no reason to free additional memory.

In your first case, dataIndex isn't even a pointer, it's an array, so you shouldn't free it itself. dataIndex[n] are pointers to the other arrays you created, but the arrays they point at were still not created dynamically, so they don't need to be freed either.

Finally, again as you guessed, you shouldn't call free for your text string, because you didn't allocate it - the compiler did.
 
When I have something like char* test = malloc(1000), I call free(test) at the end of the program. However, what if I have:

Code:
unsigned char data1[] = {blah blah blah};
unsigned char data2[] = {blah blah blah blah};
unsigned char data3[] = {blah bla};

unsigned char* dataIndex[] = {data1, data2, data3};
After I'm done with everything, should I call free(datIndex)? or free(dataIndex[n])? My gut says I shouldn't do either, but I'd hate to have memory leaks :-\

Finally, what about char* text = "Hello world" - should I call free(text)? Again I myself think I shouldn't, because I didn't dynamically allocate any memory, but I'm having doubts. All C books I have refer to pointers either by address or by malloc(), so I'm left with this bit of confusion.

Thanks

- Alex

One is dynamic, the other is static. You cannot free what has not been allocated. If using dynamic allocations might want to initialize your pointers to NULL and test to see if it was allocated before using it or especially before calling free on it, common error is calling free twice on the same pointer, avoid that one. If you allocate an array of structures you only need to deallocate or free the base of the array.

Food for thought:

short i, x, y;
double **array;

array = ( double **)malloc( y * sizeof( double *));
*array = ( double * )malloc( x * y * sizeof( double ));
for( i = 1; i < y; ++i )
*( array + i ) = *( array + i - 1 ) + x;

// can now use as:
array[ y ][ x ] = 12345.123;

.. always free in the exact opposite order of allocation.

unsigned char data3[] = {blah bla};
is exactly the same as saying:
unsigned char data3[ 2 ];
only initialized to something, it has a fixed size and should not be allocated.
 
Last edited by a moderator:
All right, this is just what I wanted to know, so only dynamically allocated memory should be freed. Excellent, thanks for the detailed replies guys :)

- Alex
 
Although the deallocation in reverse order is not required it does help in the prevention of heap fragmentation (lots of small unallocated memory between allocated). Just remember that "free"ing a pointer does not make it NULL (you need to do that yourself). also remember that if you use threads malloc/free/calloc are not thread safe so you need to wrap them with a mutex (ignore this if you are not using threads).

Just for your information: Your local variables in each function are allocated on the stack when you enter the function (usually with a single change to the stack pointer) and at the function exit the stack pointer is moved back. This movement of the stack pointer is why you need to assume that local variables are filled with "crap" prior to setting them.

Also if you free a pointer twice you can get some very strange behavior that will leave you guessing aas to what it going on. I just had that happen to me because of a cut/paste where I forgot to change a free and the memory was freed twice. It just so happened that it worked both times and when I went to malloc again the free memory on the heap was messed up so the code crashed, but it does not always do so.
 
If using dynamic allocations might want to initialize your pointers to NULL and test to see if it was allocated before using it or especially before calling free on it, common error is calling free twice on the same pointer, avoid that one.
Keep in mind that free(NULL) is defined to do nothing, as is delete NULL in C++. NULLing out pointers after freeing them should be enough to avoid double frees. Of course, as with most secure practices in C, it can be easy to accidentally miss a case.
 
Last edited by a moderator:
For me, unless I have a specific reason to leave the pointers the way they are after freeing, I will use a macro MYFREE() to set them to NULL after freeing.

Code:
#define MYFREE(p) free(p); p=NULL;
 
For me, unless I have a specific reason to leave the pointers the way they are after freeing, I will use a macro MYFREE() to set them to NULL after freeing.

Code:
#define MYFREE(p) free(p); p=NULL;
That's a neat trick, thanks! :)

A question though: unless I plan to reuse the pointer after I free it, is there a reason why I should set it to NULL? Also, it isn't very clear to me why I should set it to NULL before calling malloc() on it, either :-\*

*Edit: unless that's to test if it was allocated properly with malloc()?

- Alex
 
Last edited by a moderator:
The usual reason for setting the pointer to NULL is so if you trying freeing it again for some reason, it won't cause problems by freeing freed memory
 
also by setting them to NULL you can check to see if it has already been freed and keep you from have a pointer to heap memory that might get reused by later malloc's after you FREE'ed it.
 
Back
Top