不正确的Malloc()三层结构?

时间:2016-11-15 21:32:45

标签: c dynamic struct malloc

我正在开发一个带有三层结构的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

1 个答案:

答案 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;
}