Louis Kuang
Louis Kuang

Reputation: 797

How to properly free char** in C

I have really been confused about this 2D char array

char **arg = malloc(sizeof(char*) * argc)
for (int i = 0; i < argc; i++)
  arg[i] = malloc(sizeof(char) * size)
...
...

Now suppose after a series of operations, I forget the variable argc, how can I free those memory? Can I do something like this? Is this absolutely correct under all circumstances?

char **tmp = arg;
while (*tmp != NULL){
    free(*tmp); 
    tmp++;
}
free(arg);

Upvotes: 2

Views: 4385

Answers (3)

cup
cup

Reputation: 8237

As others have said, the problems with freeing in a loop as shown is that an extra item (argc + 1) needs to be allocated and it has to be set to NULL. An alternative technique is to first allocate the space for the pointers as you have done

char **arg = malloc(sizeof(char*) * argc)

Then, if you know all the subsequent items are the same size, allocate it in one huge block and set the rest of the elements at spaced offsets

arg[0] = malloc(sizeof(char) * size * argc);
for (int i = 1; i < argc; ++i)
   arg[i] = arg[i - 1] + size;

Freeing the space is a doddle: no need to even remember argc

free(arg[0]); /* this will free the memory used by all the elements */
free(arg);

The big disadvantages to this technique is that if any of the array elements overrun, it will corrupt the next item. This cannot be detected so easily with a heap check unless it is the last item.

Upvotes: 0

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

No

while(*tmp != NULL){

you may reach above a point where you will dereference memory which hasn't been assigned to and trigger undefined behaviour.

Or as suggested you can explicitly assign a NULL to the last allocated pointer, and in that case it will work.

Upvotes: 3

Itay Sela
Itay Sela

Reputation: 974

if you define your char * array like this:

char **arg = calloc( 1, sizeof( char * ) * argc );

you can be sure that every undefined pointer will be equal to NULL

and then you can use the while loop almost like you suggested:

char *tmp = *arg;
while ( tmp != NULL ) {
    free( tmp ); 
    tmp++;
}
free(arg);

Upvotes: -1

Related Questions