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
print语句给出了我的期望:是
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
到目前为止,一切都对我有意义,printf语句在主要工作正常。然而,令我困惑的部分是如果我在我的主函数中放置一个for循环,就像这样
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?
为什么我的程序只在我循环时才会出错?我是否遗漏了一些关于返回指向指针数组的指针的基本知识?
2 个解决方案
#1
2
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
仅分配sizeof(void *)字节,这可能小于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.
1实际上它肯定更少,因为你至少需要sizeof(void *)+ 2 * sizeof(int),也就是说你忽略了填充。
#2
1
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
.
sizeof(Array *)只是指针的大小,而sizeof(Array)是结构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
.
但我不知道你的代码到底发生了什么,因为它在array-> items = items中出错;在我的电脑里,也许你可以尝试printf(“%d \ n”,&((*(ptr [0] +9)) - > capacity));获取地址并使用gdb计算出该地址的确切内容。
#1
2
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
仅分配sizeof(void *)字节,这可能小于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.
1实际上它肯定更少,因为你至少需要sizeof(void *)+ 2 * sizeof(int),也就是说你忽略了填充。
#2
1
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
.
sizeof(Array *)只是指针的大小,而sizeof(Array)是结构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
.
但我不知道你的代码到底发生了什么,因为它在array-> items = items中出错;在我的电脑里,也许你可以尝试printf(“%d \ n”,&((*(ptr [0] +9)) - > capacity));获取地址并使用gdb计算出该地址的确切内容。