我是新编程,我发现了一个问题,我正在定义一个像这样的 c++ 数组
double name[512][512]
但是当我在 Windows 上运行它时(它编译时没有错误)它崩溃了。当我在 Linux(Ubuntu)上运行时,它运行它应该如何运行而不会出现问题。我认为 Windows 限制了我的程序可以占用的内存,对吗?我该如何解决?感谢所有可以帮助我的人。
我是新编程,我发现了一个问题,我正在定义一个像这样的 c++ 数组
double name[512][512]
但是当我在 Windows 上运行它时(它编译时没有错误)它崩溃了。当我在 Linux(Ubuntu)上运行时,它运行它应该如何运行而不会出现问题。我认为 Windows 限制了我的程序可以占用的内存,对吗?我该如何解决?感谢所有可以帮助我的人。
我猜(因为你没有提供 MCVE)你的name
数组是一个自动变量,所以它被分配在调用堆栈上。
顺便说一句,问题不在于 RAM(由操作系统管理;用户空间程序不直接使用RAM,而是使用虚拟内存),而在于进程的虚拟地址空间(其堆栈段)。在 Linux 上,您可以使用(参见proc(5)和pmap(1))查询进程的虚拟地址空间。并阅读操作系统:三个简单的部分来了解操作系统的作用。/proc/
请注意,在 x86-64sizeof(name)
上可能是 2097152 字节。
调用堆栈的大小是有限的。在 Linux 上,通常的限制是 4 或 8 兆字节(但有办法改变它),在 Windows 上据说是 1 兆字节。你有一个堆栈溢出。
你很可能超过了这个限制。考虑使用一些动态内存分配(例如,使用new
; 但是通过使用更高级别的 C++ 构造,例如容器和智能指针,您通常应该避免显式使用它)。大多数 C++ 标准容器,特别是std::vector
(但不是std::array
)将它(堆)用于内部数据。
根据经验,每个调用帧应该相当小(例如千字节)。
如果您在 Linux 上编译,编译器可能会警告您。 g++ -Wall -Wextra -Wstack-usage=1500 -g
还要学习使用gdb
调试器。害怕未定义的行为。
您还可以使用一些额外的库,例如提供矩阵的Boost(或其他东西),或者拥有自己的Matrix
抽象数据类型(它将堆分配其数据)。注意5规则
花几周时间阅读一些优秀的C++ 编程书籍,但要注意 C++ 是一种非常困难和复杂的编程语言(因此请阅读SICP以了解更一般的编程概念并尝试一些Scheme实现,例如Racket)。稍后,您可以阅读一些有关垃圾收集的书(其中的概念与内存管理相关)。
您正在遇到堆栈溢出。
sizeof(double)
在 Windows 上为 8。
因此,8*512*512
是2MB
。如果我没记错的话,Visual Studio 编译器的默认堆栈大小是 1MB。链接器上的/STACK编译器开关可用于增加此大小。
正如其他人可能指出的那样,对于大型数组,使用堆(malloc/new、free/delete)而不是使用数组变量占用大量堆栈。
您可能正在尝试在堆栈上分配数组,而 Windows 系统上的堆栈大小较小。如果是这种情况,请将数组设为全局或static
,问题就会消失。
另一种选择是动态分配数组。例如:
struct Array {
double vals[512][512];
};
// in a function:
auto name_guard = std::make_unique<Array>();
auto &name = name_guard->vals;
这里name_guard
确保在不再需要时(由 的生命周期确定name_guard
)将删除存储,并且与问题中name
的含义相同name
。注意name
一定不能让守卫对象活得更久。