【问题标题】:Seg Fault when accessing an array initialised with malloc访问使用 malloc 初始化的数组时出现段错误
【发布时间】:2017-07-24 11:55:17
【问题描述】:

下面是我正在编写的程序的简化摘录。我在访问数组末尾的元素时遇到问题。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int n, char *args[n]){

    // create 4D array scores[10000][100][100][100] on heap

    uint64_t arraySize = 1;     // this avoids overflow
    arraySize *= 10000;
    arraySize *= 100;
    arraySize *= 100;
    arraySize *= 100;

    int (*scores)[10000][100][100] = malloc(arraySize);

    for (int i = 0; i < 10000; i++) {
      for (int j = 0; j < 100; j++) {
            printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
      }
    }
  }

程序循环遍历 4D 数组 score,作为测试,我正在打印数组的内容。循环按计划开始,以“i, j, 0”的格式打印每个 ij,直到最后一次成功“25,0,0”。
从这一点开始,我得到的是随机数而不是 0,从“25、1、1078528”开始直到“25、45、1241744152”,然后是“分段错误(核心转储)”。

在摆弄之后,我发现第一个非零数组成员是 scores[25][0][7][64]

所以我想我的空间已经用完了,所以正在访问我不应该访问的内存?如果有人知道或知道如何解决此问题,我将不胜感激。

我的电脑运行的是 Ubuntu 16.10 64 位,有 16GB RAM 和 16GB 交换空间

编辑

执行以下建议后,我得到一个返回值“calloc: Cannot allocate memory”

int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));

if (scores == NULL) {
  perror("calloc");
  return 1;
}

如果我注释掉新的 if 语句(并运行 for 循环),我会立即收到 seg 错误。如果我使用 malloc,也会发生这种情况:

int (*scores)[100][100][100] = malloc(arraySize * sizeof(int));

为什么会这样?我的系统肯定有足够的内存
干杯

【问题讨论】:

  • 您没有初始化数组元素。为什么你期望它们为 0?
  • 你在做什么......你最好使用linked lists.

标签: c arrays multidimensional-array segmentation-fault malloc


【解决方案1】:
  • 查看malloc()的返回值,判断是否分配失败。
  • 您忘记乘以 int 的大小。
  • result 的类型应该是int (*)[100][100][100],而不是int (*)[10000][100][100]
  • 使用通过malloc() 分配但未初始化的缓冲区的值会调用未定义的行为,所以不要这样做。

试试这个:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int n, char *args[n]){

    // create 4D array scores[10000][100][100][100] on heap

    uint64_t arraySize = 1;     // this avoids overflow
    arraySize *= 10000;
    arraySize *= 100;
    arraySize *= 100;
    arraySize *= 100;

    int (*scores)[100][100][100] = calloc(arraySize, sizeof(int));

    if (scores == NULL) {
      perror("calloc");
      return 1;
    }

    for (int i = 0; i < 10000; i++) {
      for (int j = 0; j < 100; j++) {
            printf("%d, %d, %d\n", i, j, scores[i][j][0][0]);
      }
    }
}

【讨论】:

  • 注意calloc(10000, sizeof *scores)可以使用(按照通常的alloc成语),不需要arraySize
  • 谢谢!我运行了您的代码并收到错误“calloc:无法分配内存”。有点像预期的,但我认为 16gb 就足够了..
【解决方案2】:

指向可变长度数组的指针未使用正确的数组大小。

数组为:[10000][100][100][100]

但指针是:[100][10000][100][100]

您需要将数组大小乘以对象的大小,在本例中为 int 类型的大小。

指针定义应该是:

int (*scores)[100][100][100] = malloc(arraySize*sizeof(int));

分配的元素未初始化。读取它们将产生不确定的值。


存储需要分配的字节大小的正确类型是 size_t,而不是 uint64_t。

分配数组的正确方法之一是:

const size_t bytes = sizeof( int[10000][100][100][100] );
int (*scores)[100][100][100] = malloc( bytes );

(这当然假设 size_t 可以表示该值。)

【讨论】:

    【解决方案3】:

    你试过了吗:

    int (*scores)[10000][100][100] = malloc(sizeof(int)*arraySize);
    

    再见。

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 2020-12-28
      • 2011-12-20
      • 1970-01-01
      • 2016-09-27
      • 2020-07-30
      • 2013-10-04
      相关资源
      最近更新 更多