Reputation: 5836
I got the following code
int rows = 123;
int cols = 12;
char ***data = (char ***)malloc(rows * sizeof(char **));
if(data) {
for(int i = 0; i < num_rows; i++)
{
data[i] = (char **)malloc(cols * sizeof(char *));
if(!data[i])
{
for(int j = 0; j < i; j++)
free(data[j]);
free(data);
printf("no memory\n");
return -1;
}
}
}
char randomData[] = "<Inserts random string here everytime>";
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
data[row][col] = (char *) malloc(sizeof(char) * (1 + strlen(randomData)));
strcpy(data[row][col], randomData);
}
}
This example I wrote for this stackoverflow because real code is similar but <Inserts random string here everytime>
is output from each SQL row and each column.
I just want to make a multi-dimensional array like data[row][column]
How do I free it up properly when I am done?
I was thinking to clear it up I have to first clear the first star. char *
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
free(data[row][col]);
}
}
Then clear up the second star char **
for(int row = 0; row < rows; row++) {
free(data[row]);
}
Then I can finally clear the last triple star char ***
free(data);
Is this how you do it? seems like a overkill too much free's.. is the
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
free(data[row][col]);
}
}
enough?
Upvotes: 2
Views: 282
Reputation: 148890
You must de-allocate everything you malloc'ed.
At most you can save a loop by writing :
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
free(data[row][col]);
}
free(data[row]);
}
free(data);
If you want to de-allocate in a single pass, you must allocate in a single pass, but it is tricky for an array of pointers and must be commented in a red flashing font :
data = malloc(rows * (1 + cols) * sizeof(void *));
for (i=0; i<rows; i++) {
data[i] = &(data[cols * i]);
}
De-allocate would then be :
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
free(data[row][col]);
}
}
free(data);
If you prefer, you can allocate directly a 2D array :
data = malloc(rows * cols * sizeof(void *));
But then, you must access to the individual elements by data[j + i * rows]
... to be commented in red flashing font ...
Upvotes: 2
Reputation: 22457
Every single call to malloc
needs a single call to free
. You already outlined the correct (!) way to free up all allocations. The number of free
s should not be a problem (after all, you have no problem with the exact same number of calls to malloc
).
If you want to test to be sure, add some low-level debugging code:
int number_of_allocations = 0;
at the top of your routine.malloc
.free
.As far as I can tell, there should be no leak in there.
Upvotes: 2
Reputation: 612
You need to free as much as you malloc
To free the whole array it depends on your array dimension,
lets see first how you allocate this array :
1 - char ***array = char pointer to 2d arrays (A)
2 - **array= char pointer to 2d array (B)
3 - *array= char pointer to (vector) of char (C)
if you have ***array you need to start by :
1 - freeing each vector of your inner array (C)
2 - freeing inner array pointer (B)
3 - freeing the main pointer (A)
for your example you can do :
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
free(data[row][column]);
}
free(data[row]);
}
free(data);
Upvotes: 2