Reputation: 1844
I'm trying to understand how a pointer to an array of pointers works.
I have the following struct
typedef struct Array {
int capacity;
int size;
void **items;
} Array;
and the following function which allocates memory for the struct and returns a pointer to it
Array *createArray(int capacity) {
Array *array = malloc(sizeof(Array *));
array->capacity = capacity;
array->size = 0;
void **items = malloc(sizeof(void *) * array->capacity * sizeof *items);
if(items == NULL) {
exit(1);
}
array->items = items;
return array;
}
Now, I want to initialize an array of pointers to this struct. Here's how I am doing that
Array *(*createHashTable(int size))[10] {
Array *array[10];
int i = 0;
for(i = 0; i < size; i++) {
array[i] = createArray(size);
}
Array *(*ptr)[10] = &array;
for(i = 0; i < size; i++) {
printf("%d\n", (*(ptr[0] + i))->capacity);
}
return ptr;
}
The print statement gives me what I expect: which is
10
10
10
10
10
10
10
10
10
10
Now, my main function
int main(int argc, char *argv[]) {
Array *(*ptr)[10] = createHashTable(10);
printf("%d\n", (*(ptr[0]+9))->capacity);
return 0;
}
So far, everything makes sense to me, with the printf statement in main
working fine. However, the part that confuses me is if I place a for loop inside my main
function like so
int main(int argc, char *argv[]) {
Array *(*ptr)[10] = createHashTable(10);
int i = 0;
for(i = 0; i < 10; i++) {
printf("%d\n", (*(ptr[0] + i))->capacity);
}
return 0;
}
I get the following output,
10
10
Segmentation fault: 11
Why is my program seg faulting only when I loop? Am I missing something basic about returning a pointer to an array of pointers?
Upvotes: 1
Views: 645
Reputation: 53006
First. The problem appears to be that you are not allocating enough memory,
Array *array = malloc(sizeof(Array *));
allocates only sizeof(void *)
bytes, and that's probably less than sizeof(Array)
1
So when you try to initialize the returned array
you are accessing memory that you did not allocate, thus invoking undefined behavior.
To be always right on the ammount of memory, use the following syntax
Array *array = malloc(sizeof(*array));
this way you ensure that you are allocating the correct size.
Second. If you see that the values were printed as expected, blame it on undefined behavior. Because your code has invoked it, it will not go away after you did, and the problem will appear sooner, later or perhaps never, but it's still there. That's the worst thing about undefined behavior, since it's undefined you cannot predict when or whether it will happen.
1In fact it's surely less, because you need at least sizeof(void *) + 2 * sizeof(int)
, that is if you ignore padding.
Upvotes: 2
Reputation: 91
Array *array = malloc(sizeof(Array *));
should be
Array *array = malloc(sizeof(Array));
sizeof(Array *)
is just size of a pointer, while sizeof(Array)
is size of the structure Array
.
But I don't know exactly what happened in your code, as it went wrong at array->items = items;
in my computer, maybe you can try printf("%d\n", &((*(ptr[0]+9))->capacity));
to get the address and work out what exactly is in this address with gdb
.
Upvotes: 1