我正在开发一个带有三层结构的C程序(Linux,GCC):
typedef struct innerThing{
int data;
} inner;
typedef struct middleThing{
size_t elements;
inner collection[];
} middle;
typedef struct outerThing{
size_t outerElements;
size_t totalElements;
middle collection[];
} outer;
使用本网站上的其他帖子,我拼凑了应该构建这些结构的2D系统的代码。当我malloc()我需要的空间然后走过它,一切看起来很好:
int main(){
outer* outerThing = (outer*)malloc(sizeof(outer) + (4*sizeof(middle)) * (6*sizeof(inner)) );
outerThing->totalElements = 4 * 6;
outerThing->outerElements = 4;
int i, j;
middle* ptr1;
inner* ptr2;
// Have to manually set the "elements" metadata for middle structs
for(i=0, ptr1 = outerThing->collection; i<outerThing->outerElements; ptr1=ptr1+1, i++){
ptr1->elements = 6;
}
for(i=0, ptr1=outerThing->collection; i<outerThing->outerElements; ptr1=ptr1+1, i++){
for(j=0, ptr2=ptr1->collection; j<ptr1->elements; ptr2=ptr2+1, j++){
printf(".");
}
printf("\n");
}
free(outerThing);
return 0;
}
输出是:
[Linux]$ gcc -Wall threeStructs.c
[Linux]$ ./a.out
......
......
......
......
[Linux]$
非常令人鼓舞......虽然我期待着每列六颗星的四列。也许这是第一个问题。然而,让我疯狂的是当我修改嵌套循环以插入数据时:
for(i=0, ptr1=outerThing->collection; i<outerThing->outerElements; ptr1=ptr1+1, i++){
for(j=0, ptr2=ptr1->collection; j<ptr1->elements; ptr2=ptr2+1, j++){
printf(".");
ptr2->data=0; // <<< Added
}
printf("\n");
}
现在程序的行为发生了变化。当我重新运行它时,我看到了:
[Linux]$ gcc -Wall threeStructs.c
[Linux]$ ./a.out
......
[Linux]$
我已经通过GDB介绍了这一点,我注意到第一个内部循环运行正常。但是,剩余的内部循环永远不会运行,因为ptr1->elements
以某种方式被覆盖为6到0.当我将ptr2->data
行设置为9或7或i + j时,程序seg出错;在这些情况下,ptr1->elements
被覆盖0到12898794682。
我确信当我在内部结构中设置数据时,它会以某种方式覆盖中间结构中的数据。如果我不得不猜测,那是因为我的malloc()调用太原始了?我应该malloc()为外部结构,然后是中间结构,然后是循环中的内部结构?如果是这样,在循环中执行malloc()是否有任何危险?我认为这是一个C编码禁止。
谢谢! -Pete
答案 0 :(得分:1)
我无法让它发挥作用。我只能使用两层结构,而不是三层结构。
然而,我想到我只有一个外部结构。所以我用一个在main()
中声明的数组替换它。语义有点奇怪,但这个解决方案有效。这是代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NUM_SETS 10
#define NUM_LINES 20
typedef struct innerStruct {
int data;
} inner;
typedef struct middleStruct {
size_t elements;
inner collection[];
} middle;
int main(){
middle* arr[NUM_SETS];
inner* ptr;
int i, j;
// set up the array
for(i=0; i<NUM_SETS; i++){
arr[i] = (middle*)malloc(sizeof(middle) + (NUM_LINES * sizeof(inner)) );
arr[i]->elements = NUM_LINES;
}
// Test populate the array
for(i=0; i<NUM_SETS; i++){
for(j=0, ptr=arr[i]->collection; j<NUM_LINES; j++, ptr=ptr+1){
ptr->data=i+j; // or whatever
}
}
// free everything
for(i=0; i<NUM_SETS; i++){
free(arr[i]);
}
return 0;
}