段错误:栈溢出

4
以下内容出现在linux 2.6.32-220.7.1.el6.x86_64g++ 4.4.6中。
以下代码:
#include <iostream>
#include <cstdlib>

int PROB_SIZE   = 10000000;
using namespace std;

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

    unsigned int numbers[PROB_SIZE];
    cout << "Generating " << PROB_SIZE << " random numbers... " << flush;

    return 0;
}

请产生以下的SIGSEGV错误: (gdb) run 启动程序:/home/cpd20202/sorting/error
Program received signal SIGSEGV, Segmentation fault.
0x000000000040093b in main (argc=1, argv=0x7fffffffe4f8) at error.cpp:13
13      cout << "Generating " << PROB_SIZE << " random numbers... " << flush;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.el6_2.5.x86_64 libgcc-4.4.6-3.el6.x86_64 libstdc++-4.4.6-3.el6.x86_64
(gdb) where
#0  0x000000000040093b in main (argc=1, argv=0x7fffffffe4f8) at error.cpp:13

我真的没什么好主意了。
5个回答

8
由于您的数组比栈的大小要大,因此当函数调用期间程序试图推送新内容时,您的程序崩溃了。
您得到的错误概念上与堆栈溢出相同,只是由于本地变量非常大而不是由于嵌套太多函数调用引起的。
堆栈是一个小的内存区域,用于函数进行清理和本地变量。 它从来没有真正变大,最多几兆字节。 这就是为什么您需要动态分配以解决问题的原因。 大多数动态分配将挖掘堆,通常仅受物理内存的限制。
您需要在堆上分配数组。 为此,您有几个选项,其中最简单的可能是使用std :: vector 。 它们的行为与普通数组大致相同,并且它们的存储自动管理,因此这不应该是问题。
#include <vector>
#include <iostream>

int PROB_SIZE   = 10000000;
using namespace std;

int main()
{
    vector<int> numbers(PROB_SIZE);
    cout << "Generating " << PROB_SIZE << " random numbers... " << flush;

    return 0;
}

最简单,通常也是最有效的。 - chris

5

你的“numbers”数组是在栈上分配的,可能太大了。你需要动态分配数组。


1
这台机器有48GB的内存... - RSFalcon7
3
@RSFalcon7,那是堆大小。栈要小得多。因此,您需要在堆上分配内存,而不是在栈上分配。 - chris
1
@RSFalcon7 系统中的内存数量与堆栈大小无关,通常为 ~1MB。 - Seth Carnegie
@RSFalcon7,内存的数量与堆栈的大小无关。进程开始时有一个(小)固定的内存量供函数和函数调用使用。如果需要更多内存,则需要利用“堆”,它具有所有物理内存的潜力。 - zneak
1
@RSFalcon7,将其全局声明意味着它不再分配在堆栈上。回应您之前的帖子,堆栈大小取决于机器。如果您真的想要增加它,可以这样做。 - chris
显示剩余2条评论

3

您的进程没有足够的堆栈空间来分配一千万个整数。这是40兆字节(如果您的int是64位,那么是80兆字节)。通常情况下,进程的堆栈大小约为1兆字节。

您有两个基本选择:

  • 将数组声明为全局变量(将其声明移动到main之外)。
  • 使用mallocnewstd::vector在堆上分配您的数组。

2
尽管这可能解决眼前的问题,但我建议不要将变量移动到全局范围。 - zneak
...或者通过将其定义为“static”(尽管“std :: vector”可能是正确的选择)来保持局部范围并使其具有静态存储期。 - Jerry Coffin

0

你为栈分配的空间太大了(1000万个整数是非常大的数量)。

如果你确实需要这么多,我建议你使用堆空间,方法如下:

malloc(sizeof(int) * 10000000);


0

这不是cout的问题。你在堆栈上分配了一个非常大的数组numbers,导致堆栈溢出。堆栈通常只有8MB左右,而该数组大约为40MB。

int v[size]; // stack
int v* = new int[size]; // heap

1
@chris 在我的普通Ubuntu(amd64)机器上,ulimit -s返回8192。 - Anycorn
从我看到的大多数人来看,它是1MB,除非他们更改了它。这肯定因人而异,但我相信1MB是最常见的。 - chris
@chris 嗯,我刚测试了五台Linux机器(全部都是x64),最低的是8MB,可能跟32/64位有关。 - Anycorn
1
我在我的x64 Windows上测试了这个,它似乎只有2MB左右。 - chris
我知道“then”的区别;) 但我不知道的是我的堆栈只有1MB: $ulimit -s 10240 - RSFalcon7
@RSFalcon7,那是10MB。限制在1024个块中。 - Anycorn

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