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