Grant Sanders
Grant Sanders

Reputation: 337

Freeing dynamic 2D array not working as expected in C

When I run code like the following:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    int i, count = 0x09;
    int sizei = 5, sizej = 2;

    int **ary = malloc (sizei * sizeof **ary);
    for (i = 0; i < sizei; i++) {
        *(ary + i) = malloc (sizej * sizeof *(ary + i));
        **(ary + i) = ++count;
        printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
    }

    puts("----");
    for (i = sizei - 1; i >= 0; i--) {
        printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
        free (*(ary + i));   
    }
    puts("----");

    free (ary);
    return 0;
}

I would expect that the first half would create a 2d dynamic array of ints called ary (i.e a pointer to a dynamically allocated array of pointers, each pointing to a dynamically allocated array of ints). The 0th element of each array **(ary + i) would then be recursively assigned the current value of count.

The second half would iterate in reverse, freeing each element of ary in the reverse it was malloc'd, followed by freeing ary itself.

This appears to work fine until I try to free *(ary + 0), at which point I get a double free / corruption error. I've included the output.

  0 |0x1d6f010| +a+ 
  1 |0x1d6f018| +b+ 
  2 |0x1d6f020| +c+ 
  3 |0x1d6f028| +d+ 
  4 |0x1d6f030| +e+ 
----
  4 |0x1d6f030| +e+ 
  3 |0x1d6f028| +d+ 
  2 |0x1d6f020| +c+ 
  1 |0x1d6f018| +b+ 
  0 |0x1d6f010| +1d6f0b0+ 
*** Error in `./a.out': double free or corruption (out): 0x0000000001d6f030 ***

I'm curious why the 0th element of the 0th element of ary (i.e *(*(ary + 0) + 0)) or just **ary) became what looks like some memory address (only slighly) out of bounds from what's taken up by this 2d array once it got out of the first loop.

And if I get rid of the second loop and just try to free ary directly without first freeing any of its elements I get something like:

  0 |0x1d6f010| +a+ 
  1 |0x1d6f018| +b+ 
  2 |0x1d6f020| +c+ 
  3 |0x1d6f028| +d+ 
  4 |0x1d6f030| +e+ 
----
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000001d6f010 ***

I don't understand what I've done wrong here. Would using array notation make a difference? I need any solutions to allow me to have a dynamic length of each array independant of the length of the rest of the elements of ary if at all possible. The number elements of ary wouldn't necesarily be known at compile time either. I'm using gcc 4.9 if that's relevant.

Upvotes: 0

Views: 192

Answers (2)

Frederic Lachasse
Frederic Lachasse

Reputation: 721

ari is pointer a to array of pointer, so size of elements are pointers. In your code, you use sizeof **ary which is an int

    int **ary = malloc (sizei * sizeof **ary);

For each of the pointer to array of int elements. In your malloc for those pointers, you use sizeof *(ary+i) which is a pointer to int

        *(ary + i) = malloc (sizej * sizeof *(ary + i));

sizeof(int) is not always the same as sizeof(int*). In fact, on most 64 bits systems, which I suspect is what you use, sizeof(int)==4 and sizeof(int*)==8.

My guess is that you are using such a system, and because of that, you do not allocate enough memory for the main ari pointer and you are overflowing it with values, thrashing the content of critical memory management data so future malloc() and free() call have a big chance of failing completely.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206607

Problem 1

int **ary = malloc (sizei * sizeof **ary);

is equivalent to

int **ary = malloc (sizei * sizeof int);

If sizeof a pointer is less than sizeof(int) in your system, you end up accessing memory out of bounds.

You need to use:

int **ary = malloc (sizei * sizeof *ary);

or

int **ary = malloc (sizei * sizeof(int*));

Problem 2

*(ary + i) = malloc (sizej * sizeof *(ary + i));

needs to be

*(ary + i) = malloc (sizej * sizeof **(ary + i));

or

*(ary + i) = malloc (sizej * sizeof int);

or

ary[i] = malloc (sizej * sizeof *ary[i]);

or

ary[i] = malloc (sizej * sizeof int);

Upvotes: 2

Related Questions