简体   繁体   中英

Freeing multidimensional arrays in C

Let's say we have:

void createMultiArray(){
    int i,j;
    char*** codes = malloc(5 * sizeof(char**));
    for ( i = 0; i <= 4; i++ ) {
        codes[i] = malloc((i+1) * sizeof(char*));
        for ( j = 0; j <= i; j++ ) {
            codes[i][j] = malloc(2 * sizeof(char));
        }
   }

How should I free codes ?

free(codes);

or

int i,j;
for(i = 0; i <=4; i++){
    for(j = 0; j <= i; j++){
        free(codes[i][j]);
    }
    free(codes[i]);
}
free(codes);

Think about it this way - you should have a free for every malloc .

// you're allocating memory for codes
// must be freed with free(codes);
char*** codes = malloc(5 * sizeof(char**));

for ( i = 0; i <= 4; i++ ) {

    // allocating memory for every element in codes
    // must be freed with free(codes[i]);
    codes[i] = malloc((i+1) * sizeof(char*));

    for ( j = 0; j <= i; j++ ) {

        // allocating memory for every element in every element in codes
        // must be freed with free(codes[i][j])
        codes[i][j] = malloc(2 * sizeof(char));

    }
}

So yes, your second option is the correct one.

The second one is what you want, free can't and won't work recursively. Each time when you do a malloc think of the place where you're going to call free .

As a side note, don't free the memory if the next thing you'll do is exit the program - it's pointless and could take quite a bit of time.

The second is correct, while the first one leaks memory. As a rule of thumb, you want to call free() for every malloc() call.

Preferably you don't use nested malloc()-s, if you can calculate the size of the array beforehand. You should allocate and free in one step ( making your life easier and reducing the chance of bugs ).

The memory layout for createMultiArray() would be as follows:

            codes[i]       codes[i][j]
***         **             *      
+-+         +-+            +-+-+
|0|-------->| |----------->| | | 
+-+         +-+            +-+-+
|1|-----+                   | | 
+-+     |   +-+             | | 
|2|     +-->| |             | +------------- char
+-+         +-+             +--------------- char
|3|         | + 
+-+         +-+ 
|4| 
+-+         ....            ....

Now, go back and free each memory you've created using free [yeah, for each malloc() there should be a free() ]

OTOH, are you sure you want to do this?

for ( i = 0; i <= 4; i++ ) {
    codes[i] = malloc((i+1) * sizeof(char*));
    ....
}

for i=0, malloc will create 1 memory cell
for i=1, malloc will create 2 memory cell
for i=2, malloc will create 3 memory cell
for i=3, malloc will create 4 memory cell
for i=4, malloc will create 5 memory cell

Is this intentional?

Don't use such complicated allocation schemes to emulate multidimensional arrays. In your case in particular, where all bounds are compile time constants.

char (*codes)[n][m] = malloc(sizeof(char[x][n][m]));

fulfills the same purpose and only needs one

free(codes);

at the end. If the context where you use that array is even bound to one scope and your bounds are small you could even allocate it directly as auto variable and even initialize it at the same time

char codes[23][2][5] = { { { 'a', 'b'}  } };

no need to free at the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM