今天我正在帮助我的一个 friend 编写一些 C 代码,我发现了一些奇怪的行为,我无法向他解释为什么会发生这种情况。我们有一个包含整数列表的 TSV 文件,每行有一个 int
。第一行是列表的行数。
我们还有一个带有非常简单的“readfile”的 c 文件。第一行被读取到n
,行数,然后有一个初始化:
int list[n]
最后是 n
和 fscanf
的 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 内存被分成几个区域,包括堆栈(用于函数调用和局部变量)和堆(用于 malloc
ed 对象)。堆栈的大小通常比堆小得多;通常它大约是 8MB。因此,如果您尝试使用
int array[n];
那么你可能会超出堆栈的存储空间,导致段错误。另一方面,堆通常有很大的大小(比如,系统上有多少空间可用),因此 malloc
一个大对象不会导致内存不足错误。
一般来说,要小心 C 中的可变长度数组。它们很容易超过堆栈大小。首选 malloc
除非您知道大小很小或者您确实只需要短时间的数组。
关于c - 数组类型和使用 malloc 分配的数组之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10575544/