【问题标题】:when stack overflow happens [closed]当堆栈溢出发生时[关闭]
【发布时间】:2014-07-20 18:33:36
【问题描述】:

当我运行这样的程序时:

int main()
{
    int A[600000];
    return 0;
}

运行后出现 Windows 错误“程序已停止工作”,但在以下情况下:

int main()
{
    int A[500000];
    int B[500000];
    return 0;
}

一切似乎都很好。是因为在第一个示例中堆栈溢出了吗?我曾经认为每个函数中的变量都放在同一个堆栈中,但我可能错了。是否有可能在函数中创建太多的对象来处理?什么时候太多?

【问题讨论】:

  • 是的,大多数操作系统都对堆栈大小施加了限制。在类 unix 操作系统上,您可以使用 ulimit 更改该限制。但是,除非您澄清“它会出现错误”实际上是什么,否则您将得到的只是猜测。
  • 请注意,我在 Linux 中运行这两个程序都没有问题。不,它不会通过魔法将 B 放在堆上。
  • “运行后出现错误”什么错误?
  • 请考虑更新问题标题以更清楚地表达意思。

标签: c++ memory stack


【解决方案1】:

“It come up with errors after running 让我吃惊,因为运行时错误与环境的内存限制有关(例如堆栈溢出或机器的内存已用完)对于您的两个示例代码都是一样的。

我只能以600 000 000 的大小重现它,即:

int main()
{
    int A[600000000];
}

在 32 位平台上这是一个废话,已经被编译器停止:

错误:数组‘A’的大小太大”

因为它试图创建一个大小超过 2GB 的内存块,在 32 位平台上无法寻址...而在这种情况下允许使用 2 个大小为 500 000 000 的数组:

int main()
{
    int A[500000000];
    int B[500000000];
}

在这里做的一个合理的事情是简单地避免在堆栈上分配大内存块并将其放在堆上。例如,使用已经提到的std::vector,它本身将驻留在堆栈上,但在堆上管理其内部存储:

std::vector<int> v(600000);

在这种情况下会产生一个大小约为 2.3MB 的内存块,并在堆上分配。

【讨论】:

    【解决方案2】:

    你是对的,你溢出了堆栈保留大小(至少在 Visual Studio 方面)。堆栈保留大小与单个变量的内存大小有关,您只需在第一个sn-p中达到限制即可。

    如果您使用的是 Visual Studio,那么您可以在项目属性中更改堆栈保留大小:

    属性 -> 配置属性 -> 链接器 -> 系统 -> 堆栈保留大小

    【讨论】:

    • 如果每个线程只有 1 个堆栈,为什么在第二个示例中没有溢出?
    • 听起来你在谈论不同的调用堆栈。调用堆栈是关于函数调用的,您可以在 Visual Studio 的调用堆栈窗口中看到它。您也可以溢出调用堆栈,也可以增加调用堆栈大小。没有什么可以阻止您像在第二个 sn-p 中那样编写代码,也没有任何类型的堆栈问题。您可能会多次写入数组变量,直到程序失败,但这很可能是内存不足错误(您的 RAM)。
    • 所以一个线程有一个固定大小的函数调用栈,每个变量或数组都有它自己的固定大小的栈来放置?对不起,如果这听起来很荒谬或什么,但我很困惑
    • 差不多就是这样,这里有另一种解释en.wikipedia.org/wiki/Stack_overflow#Very_large_stack_variables
    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 2016-06-02
    相关资源
    最近更新 更多