Reputation: 797
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
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
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
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