C++ 全局数组和非全局数组之间的区别(Stackoverflow 异常)[重复]

问题描述 投票:0回答:3

当我编写以下程序时,它可以正常工作,即位集数组是在 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;
}

不起作用并抛出堆栈溢出异常 enter image description here

c++ arrays out-of-memory stack-overflow bitset
3个回答
5
投票

在 main 中声明它就是在“自动存储”(又称堆栈)中声明它。在 main 之外声明它,就是在“静态存储”又名全局数据中声明它。您正在声明 大量数据。

std::bitset<5000>
在我的 VS2013 系统上是 632 字节(可能是从 5000/8 对齐)。您申报了 5000 个。 5000 * 632 = 3 160 000 字节,或大约 3 兆字节。 VS2013 中的默认堆栈大小为 1 MB,这就是您看到溢出的原因。

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

int static_int;

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

3
投票

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

编辑:这里是对内存分配的很好的解释。


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.