【问题标题】:C++ Difference between global and non-global arrays (Stackoverflow Exception) [duplicate]全局数组和非全局数组之间的 C++ 差异(Stackoverflow 异常)[重复]
【发布时间】:2014-03-18 23:02:57
【问题描述】:

当我编写以下程序时,它可以正常工作,即 bitset 数组是在 main() 方法之外声明的。

正常工作

#include <iostream>
#include <bitset>

using namespace std;

bitset<5000> set[5000];

int main(){
    cout<<"program runs fine"<<endl;
    return 0;
}

但是当我在 main 方法中创建它时,我得到了堆栈溢出异常。谁能详细解释这里发生了什么?通常我会在递归方法中看到堆栈溢出异常。那么谁在这里使用堆栈呢?

#include <iostream>
#include <bitset>

using namespace std;


int main(){
    bitset<5000> set[5000];
    cout<<"program runs fine"<<endl;
    return 0;
}

不起作用并引发堆栈溢出异常

【问题讨论】:

  • TL;DR;: 通常'非全局数组'和对它们的引用可能超出范围,并且无效 之后的任何访问!
  • 定义一个大的局部变量是获得堆栈溢出的好方法。对大变量使用动态分配。
  • 对不起,我没有明白你的意思。第二个程序甚至没有运行,但如果我将大小减小到 50,那么它运行良好,所以与内存有关,但看起来这里涉及不同类型的内存。我听说过堆栈和堆。但是这里没有动态内存分配,所以不涉及堆。
  • 只是进入黑暗,我认为@PaulR 是对的......

标签: c++ arrays out-of-memory stack-overflow bitset


【解决方案1】:

在 main 中声明它是在“自动存储”AKA 堆栈中声明它。在 main 之外声明它,就是在“静态存储”AKA 全局数据中声明它。您正在声明大量数据。std::bitset&lt;5000&gt; 在我的 VS2013 系统上是 632 字节(可能是 5000/8 的对齐)。而你宣布其中有 5000 个。 5000 * 632 = 3 160 000 字节,或大约 3 兆字节。 VS2013 中的默认堆栈是 1 兆字节,这就是您看到溢出的原因。

共有三种存储方式:自动、存储和动态。它们分别通俗地称为堆栈、静态(在某些情况下是全局)和堆内存:

int static_int;

int main() {
  int automatic_int;
  static int local_static_int; // also static storage!
  int * dynamic_int_ptr = new int;
}
  • 在编译时/运行时混合分配自动存储。堆栈在运行时扩展为函数以保存局部变量,但这是一个已知的编译时值,因为变量的数量及其大小是众所周知的(我在这里忽略动态数组,因为它们不是-standard) 这些变量在作用域入口时构造,在作用域出口时销毁。
  • 静态存储在编译时分配。该内存是预先支付的,并在程序启动时构建。程序退出时销毁。
  • 动态存储在运行时分配。此内存由new 分配,并返回指向保存闪亮新数据的某个 blob 的指针。这些变量在调用new 时构造,在调用delete 时销毁。

【讨论】:

  • 那么基本上有三种类型的存储——堆栈、堆和静态存储/全局数据?我只听说过前两个。
  • @VVV 我用更多信息更新了我的答案!如果您需要进一步说明,请告诉我
  • 谢谢哥们。我看到了 Nilesh 的答案链接,事实证明实际上有 5 种类型的内存。是时候刷新我的 c++ 了!已经嵌入 c# 世界很长一段时间了。
  • @VVV 这个答案很好,但实际上非常特定于平台。 C++ 没有提到.data.bss,它们是关于如何实现静态存储的解决方案。就 C++ 而言,存储只有 3 种:自动、静态和动态。
  • @SamCristall:我同意你的看法。流程中的段组织可能因平台而异,并且实现静态存储的方式也可能不同。
【解决方案2】:

因为当您将数组声明为全局时,内存分配在进程的数据段中,而当您尝试在函数中声明它时,内存分配在堆栈上。由于您分配了大量内存,因此会导致 stackoverflow 异常。

编辑:Here 很好地解释了内存分配。

【讨论】:

  • 谢谢,内存有 3 种类型 - 堆栈、堆和静态存储/全局数据/数据段?
  • 感谢您的链接好友。所以现在事实证明有 5 种类型的存储。谢谢。
【解决方案3】:

您正在尝试在程序堆栈上创建 (5000*5000)/8 字节 - 3Megs 的数据,这会导致所报告的堆栈溢出。您的程序中没有足够的堆栈空间来执行此操作。当您将其创建为全局时,它会插入到您的程序数据段中。

【讨论】:

  • 谢谢,但堆不是用于动态内存分配吗?所以像 int*x = new int[10000] 这样的东西将使用堆(不管它是在 C++ 函数内部还是外部)。请让我知道我的推理是否正确。
  • 你的理解是对的。当您使用 new 等运算符时,内存将在堆上分配。在您的情况下,您将其声明为全局而不是在堆上分配内存。
  • 是的。最近读了太多关于 SO 的 Heap v Stack 问题,脑子里堆满了东西。它在数据段而不是堆中,它是静态的并且取决于您的程序。注意到我正在纠正这一点。
猜你喜欢
  • 1970-01-01
  • 2011-04-27
  • 2019-12-28
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 2018-12-22
  • 2019-09-11
  • 1970-01-01
相关资源
最近更新 更多