【问题标题】:Segmentation fault: stack overflow [duplicate]分段错误:堆栈溢出 [重复]
【发布时间】:2012-05-21 12:28:39
【问题描述】:

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) 运行 启动程序:/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

我真的没有想法。

【问题讨论】:

    标签: c++ segmentation-fault stack-overflow cout


    【解决方案1】:

    您的“数字”数组正在堆栈上分配,并且可能太大。您将需要动态分配数组。

    【讨论】:

    • 本机48GB内存...
    • @RSFalcon7,这是堆大小。堆栈要小得多。因此,您需要在堆而不是堆栈上分配内存。
    • @RSFalcon7 系统内存大小与堆栈大小无关,通常为~1MB。
    • @RSFalcon7,内存大小与栈大小无关。进程从(小)固定数量的内存开始,供函数和函数调用使用。如果你需要更多,你需要挖掘“堆”,它具有你所有物理内存的潜力。
    • @RSFalcon7,全局声明它意味着它不再在堆栈上分配。为了回应您之前的帖子,堆栈大小取决于机器。如果你真的想要,你可以增加它。
    【解决方案2】:

    这是因为您的数组大于堆栈的大小。因此,您的程序在函数调用期间尝试推送新内容时会崩溃。

    您得到的错误在概念上与堆栈溢出相同,除了它是由一个非常大的局部变量引起的,而不是由嵌套过多的函数调用引起的。

    堆栈是一个小内存区域,供函数用于内务处理和局部变量。它从来都不是很大,最多只有几兆字节。这就是为什么您需要动态分配来解决您的问题。大多数动态分配都会利用堆,这通常只受物理内存的限制。

    您需要在堆上分配数组。为此,您有多种选择,其中最简单的可能是使用std::vector&lt;int&gt;。它们的行为与普通数组大致相同,并且它们的存储是自动管理的,所以这应该不是问题。

    #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;
    }
    

    【讨论】:

    • 最简单,通常也是最有效的*。
    【解决方案3】:

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

    您有两个基本选择:

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

    【讨论】:

    • 即使这样可以解决眼前的问题,我还是建议不要将变量移动到全局范围内。
    • ...或通过将其定义为static 来保持本地范围,同时为其提供静态存储持续时间(尽管std::vector 可能是正确的选择)。
    【解决方案4】:

    这不是 cout。您在堆栈上分配了一个非常大的数组 numbers 并炸毁了您的堆栈。堆栈通常为 8 MB 左右,而数组为 40 MB 左右。

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

    【讨论】:

    • @chris ulimit -s 在我的香草 ubuntu (amd64) 机器上返回 8192。
    • 根据我从大多数人那里看到的情况,除非他们更改它,否则它是 1MB。肯定会因人而异,但我很确定 1MB 是最常见的。
    • @chris 嗯,我刚刚测试了五台 Linux 机器(都是 x64),最低的是 8MB,可能是 32/64 位的东西。
    • 我在我的 x64 Windows 上测试了它,它似乎刚刚超过 2MB。
    • 我知道那时的区别;)我不知道的是我的堆栈只有 1MB:$ulimit -s 10240
    【解决方案5】:

    您为堆栈分配了太多空间来处理(1000 万个整数是非常大的数量)。

    如果你真的需要这么多,我建议你使用堆空间来代替:

    malloc(sizeof(int) * 10000000);

    【讨论】: