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

Jor*_*tao 61 c arrays malloc variable-length-array

今天我用一些C代码帮助我的一个朋友,我发现了一些奇怪的行为,我无法解释他为什么会发生这种行为.我们有一个带有整数列表的TSV文件,每行都有一个int.第一行是列表的行数.

我们还有一个非常简单的"readfile"的ac文件.第一行读到n,行数,然后有一个初始化:

int list[n]
Run Code Online (Sandbox Code Playgroud)

最后是一个带有fscanf的n循环.

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

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

int *list = malloc(n*sizeof(int))
Run Code Online (Sandbox Code Playgroud)

一切都很好,即使是非常大的n.

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

tem*_*def 145

这里有几个不同的作品.

第一个是将数组声明为的区别

int array[n];
Run Code Online (Sandbox Code Playgroud)

int* array = malloc(n * sizeof(int));
Run Code Online (Sandbox Code Playgroud)

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

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

int array[n];
Run Code Online (Sandbox Code Playgroud)

然后,您可能会超出堆栈的存储空间,从而导致段错误.另一方面,堆通常具有巨大的大小(例如,系统上空闲的空间),因此malloc大型对象不会导致内存不足错误.

通常,要注意C中的可变长度数组.它们很容易超过堆栈大小.身高:malloc除非你知道的大小是小还是你真的只做想要的短时间的阵列.

希望这可以帮助!

  • 很好的答案!我想知道速度是否也有差异? (2认同)

Set*_*gie 9

int list[n]
Run Code Online (Sandbox Code Playgroud)

堆栈n整数分配空间,这通常很小.使用堆栈上的内存比替代方法快得多,但是它很小并且很容易溢出堆栈(即分配太多内存),如果你做的事情就是分配大型数组或进行太深入的递归.您不必手动释放以这种方式分配的内存,它是在阵列超出范围时由编译器完成的.

malloc另一方面,在堆中分配空间,与堆栈相比通常非常大.您将不得不在堆上分配更大量的内存来耗尽它,但是在堆上分配内存比在堆栈上分配内存要快得多,并且必须free在完成使用后手动取消分配它.