在堆栈上分配的变量大小是否有最大限制?

10

我在C语言中声明了一个结构体变量,其大小大于1024字节。运行Coverity(一种静态代码分析器应用程序)后,它报告说此堆栈变量大于1024字节,因此是错误的原因。

我想知道我是否需要担心这个警告?单个堆栈变量的最大限制是否真的存在?

谢谢, Che


选择1024完全是任意的,一个512字节的变量也可能是“错误的原因”。而一个2048字节的变量并不会使出错的可能性增加一倍。接受这个建议时要持怀疑态度。 - Hans Passant
8个回答

3
变量的最大大小受堆栈的最大大小限制(具体而言,受堆栈中剩余的空间大小限制,包括来自堆栈上层函数的变量和参数以及进程框架开销)。
在Windows上,第一个线程的堆栈大小是可执行文件链接时设置的属性set during linking,而线程的堆栈大小可以在thread creation期间指定。
在Unix上,第一个线程的堆栈大小通常只受其增长空间的限制。根据特定Linux内存布局和共享对象的使用情况,这可能会有所不同。线程的堆栈大小也可以在thread creation期间指定。

3
它所试图保护您免受的问题是堆栈溢出。由于执行路径的不同,这很难在测试中发现。主要因为这个原因 - 在堆栈上分配大量数据被认为是不好的做法。然而,只有在嵌入式系统上才真正可能遇到实际问题。 换句话说,它设置了一个任意限制,以确定它认为堆栈上的数据量过多。

2
是的。当然,它受到您系统地址空间的限制。它还受到操作系统分配给堆栈的空间量的限制,该空间通常在程序启动后无法更改,但可以事先更改(通过启动过程或可执行文件的属性)。快速浏览一下,在我的OS X系统上,最大堆栈大小为8 MiB,在Linux上为10 MiB。在某些系统上,您甚至可以为每个不同的线程分配不同数量的堆栈,尽管这具有有限的用处。大多数编译器还有另一个限制,即单个堆栈帧中允许的最大值。

在现代桌面上,除非函数是递归的,否则我不会担心1k的堆栈分配。如果您正在编写嵌入式代码或用于内部使用的代码,则会出现问题。在Linux内核中的代码仅允许64 KiB或更少的堆栈,具体取决于配置选项。


在某些系统上,您甚至可以为每个不同的线程分配不同数量的堆栈,尽管这有限制。它在默认堆栈非常小的系统上变得有用 - 在桌面Linux上您看不到需要,但在一些预先分配堆栈且没有虚拟内存的嵌入式系统上则需要。 - Steve Jessop

1

0

据我所见,C编译器(Turbo)为变量提供了最大64000k的大小。如果我们需要更多的空间,则将其声明为“huge”。


当我将变量声明为int a [1000] [1000]时,我看到了相同的消息。编译器显示错误消息“数组大小过大”。当我查看帮助时,它给出了相同的消息。 - Y. Kiran Kumar

0

尝试使用大量的堆栈空间并不是一个好主意。

这里有一个链接到默认的gcc堆栈大小:http://www.cs.nyu.edu/exact/core/doc/stackOverflow.txt

此外,您可以指定--stack,xxxxx来自定义堆栈大小,因此最好假设xxxxx是一个小数字,并坚持使用堆分配。


0
如果您的函数涉及到递归(直接或间接),那么在堆栈上分配大量内存将限制递归深度,可能会导致堆栈溢出。在Windows下,此堆栈保留默认为1MB,但您可以使用链接器命令静态增加它。堆栈将随着使用而增长,但操作系统有时无法扩展它。我在我的网站这里中详细讨论了这个问题。

0

堆栈、堆、低、高 VM——对于第一个线程,64位VM的顶部应该没有限制,因此似乎是gcc/c编译器的一个错误,对于本地自动“int x[2621440];”,我得到了SIGSEGV。编译器应该让第一个线程的堆栈增长,直到它碰到堆,在一个16亿亿字节的VM中,这是相当不可能的。最好的解释是称其为编译器的“限制”。(在一些测试中,可能是在Solaris SPARC上进行的测试,似乎本地变量的处理速度比全局变量快。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接