Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数组类型与使用malloc分配的数组之间的差异_C_Arrays_Malloc_Variable Length Array - Fatal编程技术网

数组类型与使用malloc分配的数组之间的差异

数组类型与使用malloc分配的数组之间的差异,c,arrays,malloc,variable-length-array,C,Arrays,Malloc,Variable Length Array,今天我在帮助我的一个朋友编写一些C代码,我发现了一些奇怪的行为,我无法解释他为什么会这样。我们有一个包含整数列表的TSV文件,每行都有一个int。第一行是列表的行数 我们还有一个c文件,带有一个非常简单的“readfile”。第一行读取到n,即行数,然后初始化: int list[n] 最后是一个带有fscanf的for循环n 对于小n(直到10万),一切正常。然而,我们发现,当n很大(10^6)时,会发生断层 最后,我们将列表初始化更改为 int *list = malloc(n*sizeo

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

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

int list[n]
最后是一个带有
fscanf
的for循环
n

对于小n(直到10万),一切正常。然而,我们发现,当n很大(10^6)时,会发生断层

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

int *list = malloc(n*sizeof(int))
即使是非常大的
n
,一切都很好


有人能解释为什么会发生这种情况吗?当我们开始使用
list=malloc(n*sizeof(int))
时停止的
int-list[n]
segfault的原因是什么?

int-list[n]将数据存储在堆栈中,而malloc将数据存储在堆中


堆栈有限,没有太多空间,而堆要大得多。

int list[n]
是一个VLA,它在堆栈上而不是在堆上进行分配。您不必释放它(它在函数调用结束时自动释放),而且它分配得很快,但正如您所发现的,存储空间非常有限。必须在堆上分配较大的值。

此声明在堆栈上分配内存

    int list[n]
malloc在堆上进行分配

堆栈大小通常比堆小,因此如果在堆栈上分配太多内存,就会出现堆栈溢出


另请参见

当您使用
malloc
进行分配时,内存是从堆而不是从堆栈分配的,而堆栈的大小要有限得多

int list[n]

为堆栈上的
n
整数分配空间,通常非常小。在堆栈上使用内存比另一种方法快得多,但它非常小,如果您执行诸如分配巨大数组或递归太深之类的操作,则很容易使堆栈溢出(即分配太多内存)。您不必手动取消分配以这种方式分配的内存,当数组超出范围时,编译器会执行此操作


另一方面,
malloc
在堆中分配空间,这通常比堆栈大。您必须在堆上分配更多的内存来耗尽它,但是在堆上分配内存要比在堆栈上慢得多,并且在使用完后,您必须通过
free
手动解除分配它。

这里有几个不同的部分

第一个是将数组声明为

int array[n];

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

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

int array[n];
然后,您可能会超出堆栈的存储空间,从而导致segfault。另一方面,堆通常有很大的大小(比如,系统上的可用空间),因此
malloc
ing一个大对象不会导致内存不足错误

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


希望这有帮助

假设您的实现中有一个典型的实现,那么很可能:

int list[n]
堆栈上的已分配列表,其中:

int *list = malloc(n*sizeof(int))
在堆上分配内存


在堆栈的情况下,通常会限制它们的增长(如果它们可以增长的话)。在堆的情况下,仍然有一个限制,但这往往很大程度上(广泛地)受到RAM+交换+地址空间的限制,通常至少要大一个数量级,如果不是更多的话。

如果您在linux上,可以将ulimit-s设置为更大的值,这可能也适用于堆栈分配。 当您在堆栈上分配内存时,该内存将一直保留到函数执行结束。如果在堆上分配内存(使用malloc),则可以随时释放内存(甚至在函数执行结束之前)

通常,堆应该用于大内存分配

   int array[n];
这是一个静态分配数组的例子,在编译时数组的大小是已知的。数组将被分配到堆栈上

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

这是一个动态分配数组的示例,用户在运行时将知道数组的大小。数组将在堆上分配。

“在堆栈上使用内存比另一种方法快得多”,这里您指的是“分配”还是“访问”?好吧,堆栈分配要快得多,但它对访问(读/写)也适用吗?谢谢你的回答!我想知道在速度上是否也有差异?由于引用的局部性的影响,我怀疑堆栈分配的数组访问速度更快,而且
malloc
本身比仅仅碰撞堆栈指针慢得多。但实际上,最好使用更适合手头任务的任何方法;在任何功能之外,它们都会自动关闭
   int *array(malloc(sizeof(int)*n);