【问题标题】:Stack overflow exception in the silly program傻程序中的堆栈溢出异常
【发布时间】:2012-05-10 21:39:11
【问题描述】:

我正在使用 VS 2010。
当我在调试模式下运行此程序时,它会引发堆栈溢出异常并在文件 chkstk.asm 的第 99 行显示断线。
但是当我在 Release 模式下运行它时,它就可以了。
此外,如果我将其中一个数组的大小减小到 10000,它在 Debug 中运行良好。是什么原因?

#include <iostream>

using namespace std;
int main()
{
    char w[1000001], temp[1000001];
    cout<<"Why?"<<endl;
    return 0;
}

【问题讨论】:

  • 您在发布模式下启用了哪些优化?编译器很有可能只是删除了数组。
  • 您是在问“溢出的原因是什么?”或者“行为在不同构建模式下发生变化的原因是什么?”还是别的什么?
  • 作为我找到的可能的解决方案#pragma comment(linker, "/STACK:1000000000")
  • 它在调试模式下崩溃,因为您在堆栈上分配了太多变量。它不会在 RELEASE 模式下崩溃,因为编译器认识到您甚至没有使用 w 和 temp 并将它们优化为不存在。如果它们不存在,则不会占用堆栈空间,也不会导致堆栈溢出。

标签: c++ visual-studio-2010 visual-c++ stack-overflow


【解决方案1】:

由于堆栈非常小,在大多数系统上大约为 1MB,因此您的大缓冲区会使堆栈溢出。要解决这个问题,只需像这样在堆上分配:

#include <iostream>

using namespace std;
int main()
{
    char* w = new char[1000001];
    char* temp = new char[1000001];
    cout<<"Why?"<<endl;
    delete[] w;
    delete[] temp; 
    return 0;
}

【讨论】:

    【解决方案2】:

    堆栈非常小(~1MB)。您正在用这些数组中的大量元素填充它。

    如果您需要更多空间,请尝试在堆上分配(指针会这样做)。

    实现这一点的一个好方法是使用向量,它在内部将东西存储在堆上:

    std::vector<char> w (1000001);
    std::vector<char> temp (1000001);
    

    【讨论】:

      【解决方案3】:

      你在堆栈上分配了太多东西;可能在调试模式下,堆栈由于各种安全检查而被占用更多,或者故意变小以帮助您更早地检测到此类问题。无论如何,即使在释放模式下,使数组稍大一点也会触发堆栈溢出(除非编译器完全优化它们)。

      这里问题的根源是您不应该在堆栈上分配大的东西,堆栈的大小非常有限(在使用 VC++ 的 Windows 上默认为 1 MB)并且应该只用于小缓冲区/对象。如果您需要进行大分配,请在堆上进行(使用new/malloc),最好使用智能指针以避免内存泄漏。

      【讨论】:

        【解决方案4】:

        自动存储中的数组在堆栈上分配。堆栈空间有限。当栈空间不足以分配自动变量时,会发生栈溢出异常。

        如果您需要这么大的数组,请改用静态或动态分配。

        对于静态分配,将声明移到main()之外。

        对于动态分配,使用下面的代码:

        char *w = new char[1000001], *temp = new char[1000001];
        // Work with w and temp as usual, then
        delete[] w;
        delete[] temp;
        

        最后,考虑使用标准容器而不是普通数组:std::array 是一个更好的数组,如果你不需要调整大小(它分配在堆栈上,不会解决这个问题); std::string 也是替换 char 数组的不错选择。

        【讨论】:

        • 我认为std::array 不会解决他的问题。它将仍然在堆栈上分配数据。试试std::vector
        • @Robᵩ 你是对的,它不会!我提到std::array 作为普通数组的替代品,而不是解决这个特定问题的方法。我可以看到答案的这一部分可能会产生误导,因此为了清楚起见,我对其进行了编辑。谢谢!
        猜你喜欢
        • 2010-11-27
        • 1970-01-01
        • 1970-01-01
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        • 2016-02-19
        相关资源
        最近更新 更多