【问题标题】:2D Array of structs in C?? (maybe) [duplicate]C中的二维结构数组?? (也许)[重复]
【发布时间】:2019-03-12 03:47:02
【问题描述】:

我正在尝试创建一个二维数组,其中每个元素都指向一个结构来存储来自 CSV 文件的值。我不确定我是在创建结构还是定义二维数组。

下面是我的结构以及我如何分配内存。总会有 35 列,但行可能会变得非常大。当我使用 int test =29000(或 29000 行)运行它时,它可以工作并将所有值存储在我可以通过[row][col] 访问的二维数组中。当我用大于 29000 的任何东西分配测试时,它甚至没有进入内存的分配,它只是在struct node* arrayofnodes[test][35]; 处出现段错误。

我很困惑为什么它适用于 29000 但不适用于 30000。另外,如果有人对如何在一行上 malloc 数组而不是进入 2 for 循环有任何建议,我会很高兴学习。我也想知道我是否应该在这里使用typedef struct

谢谢

 struct node {
  char* value;
};

int test=30000;
struct node* arrayofnodes[test][35];
for (int p=0; p < test; p++){
   for (int j=0; j < 35; j++){
      arrayofnodes[p][j] = malloc(sizeof(arrayofnodes));
   }
}//this works and i can access a certain element by arrayofnodes[row][col].value;

【问题讨论】:

  • 注意:sizeof(arrayofnodes)test * 35 指针的大小 - 代码分配了 test * 35 次。
  • @Antii Haapala,标记为重复的帖子还没有回答这个问题。如果您愿意,请重新打开该问题,以便我可以添加一些额外的见解来帮助解决它。谢谢。

标签: c multidimensional-array struct


【解决方案1】:

问题可能是您在堆栈上分配了太多。 arrayofnodes 将是一个包含 30,000*35=1,050,000 个指针的数组,每个指针可能是 8 个字节。所以你试图在堆栈上分配一个 8MB 的数组,而 8MB 是堆栈大小的默认限制。

这段代码对我来说是段错误的:

#include <stdio.h>

int main() {
    struct node {
        char* value;
    };

    int test=30000;
    struct node* arrayofnodes[test][35];
    printf("%d\n", sizeof(arrayofnodes));
}

另外,sizeof(arrayofnodes) 是错误的。如果上面的代码 sn-p 没有段错误,它会打印8400000。相反,sizeof struct nodesizeof arrayofnodes[0][0] 会给出正确的结果。

解决方案可能是这样的:

struct node ** array[35];
for(int i=0; i<35; i++) {
    array[i] = malloc(test * sizeof array[0]);
    for(int j=0; j<test; j++) array[i][j] = malloc(sizeof (struct node));
}

【讨论】:

  • 我赞成你的回答,但你说错了:If the code snippet above wouldn't have segfaulted, it would have printed 22400000。它会打印 35*30000*8 = 8400000。我争论是否应该编辑您的答案,但决定将其发布为评论,以便您可以修复它。我也通过实际程序对其进行了验证,其中将 test 设置为 10000 运行(而不是出现 Segmentation fault (core dumped) 错误,并且它打印 2800000。2800000 * 3 = 8400000 以及。我真的不确定22400000 号码来自哪里。
  • 另外,您的答案的第二部分(您推荐的解决方案)也是不正确的(并且难以阅读)。对于您的第二个malloc(),您应该为struct node 的大小分配内存。然而,使用malloc(sizeof array[0][0])错误,因为它错误地将内存分配给struct node * 的大小。有效选项包括以下所有 3 个选项:sizeof(*array[0][0])sizeof(array[0][0][0])sizeof(struct node)(最后一个是推荐选项,因为它是最易读且最难搞砸的)。
  • ^^ 抱歉,这个词不是全部大写的。
【解决方案2】:

您在此处分配了 大量 内存:printf("%lu\n", sizeof(arrayofnodes)); 报告 arrayofnodes 的大小为 30000 * 35 * 8 = 8400000 字节,因此总内存分配为 30000 * 35 * 8400000 = 8820000000000 字节你的循环。

您的意思可能是*arrayofnodes[p][j]--为指向行p 和列j 的结构的指针分配空间。请注意,这不包括char * 指向的内存块的空间,这也需要malloced。

另外,请记住,虽然堆有足够的空间,但堆栈没有,8 * 35 * 30000 可能超出堆栈帧的处理能力。

如果只有一个字段,请考虑避免使用结构。使用普通的旧 char * 可以避免额外的间接层。

如果您想以牺牲速度为代价来最大化空间效率,您可以尝试一次读取您的文本文件,为每个单元格构建一个字符串大小的数组,然后 malloc 相应地第二遍读取所有内容。您可以使用char ***csv_data 数组,其中包含分配给csv_cell_size[row][col] 或类似大小的单元格。

按维度展平数组并使用偏移量来查找特定行/列是另一种选择。长话短说,管理此问题的方法不止几种,很大程度上取决于您的数据以及您计划如何使用它。

另外,完成后不要忘记free()你所有的记忆。

【讨论】:

    【解决方案3】:

    您的数组声明正在堆栈上分配,默认堆栈限制为 8MB。当 test 为 29000 时,堆栈分配在限制范围内(29000 * 35 * 8 = 7.7MB),当您将 test 更改为 30000 时,您超出了堆栈限制(30000 * 35 * 8 = 8.01MB),这导致了段错误.

    你可以通过使用 malloc 在堆上分配数组来解决这个问题,只要记住释放你分配的东西。

    #include <stdio.h>
    #include <malloc.h>
    
    struct node {
            char *value;
    };
    int rows = 30000;
    int cols = 35;
    
    struct node **arrayofnodes;
    
    int main() {
            arrayofnodes = (struct node **)malloc(rows * sizeof(struct node*));
            for (int row = 0; row < rows; row++) {
                    arrayofnodes[row] = (struct node *)malloc(cols * sizeof(struct node*));
            }
    
            // Use arrayofnodes
    
            // Free allocations after use...
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-13
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 2019-06-23
      • 2020-05-10
      相关资源
      最近更新 更多