【问题标题】:C++ stack array limit?C ++堆栈数组限制?
【发布时间】:2012-11-18 04:04:56
【问题描述】:

我正在运行一些代码,这可能会指出我不太了解堆和堆栈之间的区别。下面我有一些示例代码,我要么在堆栈上声明一个数组,要么在 1234567 个元素的堆上声明一个数组。两者都有效。

int main(int argc, char** argv){

  int N = 1234567;

  int A[N];

  //int* A = new int[N];

}

但是,如果我们将 N 设为 12345678,我会遇到 int A[N] 的段错误,而堆声明仍然可以正常工作。 (如果重要的话,我正在使用 g++ O3 -std=c++0x )。这是什么疯狂?堆栈是否有(相当小的)数组大小限制?

【问题讨论】:

  • 栈是支持函数调用执行的工作内存。它相对较小,因为大多数调用它只使用几个字节。您可以通过更改编译设置来扩展它。

标签: c++ memory heap-memory stack-memory


【解决方案1】:

堆随着 malloc 和 co 的分配而动态增长。堆栈随着程序运行过程中的每个函数调用而增长。返回地址、参数、局部变量通常存储在堆栈中(除了在某些处理器架构中,其中少数存储在寄存器中)。也可以(但不常见)动态分配堆栈空间。

堆和栈竞争使用相同的内存。您可以考虑一个从左到右生长,另一个从右到左生长。如果不加以控制,它们可能会发生碰撞。堆栈通常被限制增长超过某个界限。这是相对较小的,因为预计它将只使用几个字节来进行大多数调用,并且只使用几个堆栈级别。限制很小,但对于大多数任务来说已经足够了。您可以通过更改构建设置(但不适用于 Linux ELF 二进制文件)或调用 setrlimit 来扩展此限制。操作系统也可能会施加一个您可以更改的限制。可能有软限制和硬限制(http://www.nics.tennessee.edu/node/327)。

更详细地了解限制超出了问题的范围。底线是堆栈是有限的,而且非常小,因为它与堆竞争实际内存,对于典型的应用程序,它不需要更大。

http://en.wikipedia.org/wiki/Call_stack

【讨论】:

  • 不只是函数调用。
  • 请解释一下——我的大脑工作太晚了:-)
  • @MiltiadisKokkonidis:它也适用于自动变量
  • 局部变量是支持函数调用的一部分,因为你不能调用函数,除非你为它们分配空间并且你只为函数的局部变量分配内存来调用函数。事实上,就内存分配而言,参数和局部变量的处理方式完全相同。唯一的区别是调用者初始化参数并且函数的代码负责初始化它希望的局部变量:-)
【解决方案2】:

这是因为堆栈的大小比堆小得多。堆可以占用程序可用的所有内存。默认情况下,VC++ 编译的堆栈大小为 1 MB。堆栈提供更好的性能,但适用于更少量的数据。一般来说,它不用于大型数据结构。这就是为什么在 c++ 中接受列表/数组/字典/ect 的函数通常采用指向该结构的指针或引用。按值传递的参数被复制到堆栈中,传递这样的结构会经常导致程序崩溃。

在您的示例中,您使用的是N intint 是 4 个字节。这使得 A[N] 的大小约为 4.7 MB,远大于堆栈的大小。

【讨论】:

  • 提供比堆性能更好或更差的性能。堆栈和堆在同一个内存芯片上!是堆内存分配函数(mailloc 和 co)比分配堆栈存储的简单而快速的方式更复杂和更慢:-)
  • @MiltiadisKokkonidis 这没有任何意义。如果堆栈上的分配性能更高,则堆栈的性能更高。
  • 这很有意义。您是否认为将它们称为堆栈内存比将它们称为堆内存访问四个字节的内存更快?不。:-) 也可以分配一块 20 MB 的堆内存并将其位置存储在一个名为 fastMem 的指针中,而不是 p = malloc(n);做 p = 快速记忆;快速记忆 += p;这将使堆上的分配与堆栈中的分配非常相似,并且具有同样超快的性能。
猜你喜欢
  • 2016-06-27
  • 2010-10-28
  • 2020-06-12
  • 2018-06-06
  • 2018-09-24
  • 2015-07-02
  • 2021-02-17
  • 2012-04-02
  • 2020-03-20
相关资源
最近更新 更多