c - 数组类型和使用 malloc 分配的数组之间的区别

标签 c arrays malloc variable-length-array

今天我正在帮助我的一个 friend 编写一些 C 代码,我发现了一些奇怪的行为,我无法向他解释为什么会发生这种情况。我们有一个包含整数列表的 TSV 文件,每行有一个 int。第一行是列表的行数。

我们还有一个带有非常简单的“readfile”的 c 文件。第一行被读取到n,行数,然后有一个初始化:

int list[n]

最后是 nfscanf 的 for 循环。

对于小 n(直到 ~100.000),一切都很好。但是,我们发现当 n 很大(10^6)时,会发生段错误。

最后,我们将列表初始化改为

int *list = malloc(n*sizeof(int))

一切都很好,即使 n 非常大。

有人可以解释为什么会这样吗?当我们开始使用 list = malloc(n*sizeof(int)) 时,是什么导致了 int list[n] 的段错误?

最佳答案

这里有几个不同的部分在起作用。

首先是声明数组为的区别

int array[n];

int* array = malloc(n * sizeof(int));

在第一个版本中,您要声明一个具有自动存储持续时间的对象。这意味着只要调用它的函数存在,数组就会存在。在第二个版本中,您将获得具有动态存储持续时间的内存,这意味着它将一直存在,直到使用 free 显式解除分配。

第二个版本在这里工作的原因是 C 通常如何编译的实现细节。通常,C 内存被分成几个区域,包括堆栈(用于函数调用和局部变量)和堆(用于 malloced 对象)。堆栈的大小通常比堆小得多;通常它大约是 8MB。因此,如果您尝试使用

分配一个巨大的数组
int array[n];

那么你可能会超出堆栈的存储空间,导致段错误。另一方面,堆通常有很大的大小(比如,系统上有多少空间可用),因此 malloc 一个大对象不会导致内存不足错误。

一般来说,要小心 C 中的可变长度数组。它们很容易超过堆栈大小。首选 malloc 除非您知道大小很小或者您确实只需要短时间的数组。

关于c - 数组类型和使用 malloc 分配的数组之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10575544/

相关文章:

ruby - 按键对哈希数组进行分组

ruby - 在 Ruby 中汇总两个结果

c - ProC 在 10g 上编译并在 11g 上运行

c - 为什么调用 free() 不会减小堆的大小?

java - JNA 将 Java String 映射到 PCWSTR

c - 使用 execv 将一个进程的输出传输到另一进程的程序

c - free(temp) 指针释放链表中的头指针-如何保留指向列表原点的指针

c - 按位 & 相当于模运算

c - 声明一个结构数组

c - OpenCV (C,2.0) 输入点因内部函数变量转换而困惑