如@Ajay的回答和@Cornstalks的评论所指出的那样,您可以通过在数组上使用
static
或
constexpr
限定符来完全避免使用堆栈和堆。
const static std::array<float, 1000000> a1 = {}
constexpr std::array<float, 1000000> a2 = {}
这将把数组存储在您的内存数据初始化部分(
这里有很好的解释)。`const` 仅用于禁止修改 `a1`,并不需要避免堆栈溢出。声明为 `constexpr` 的变量也自动成为 `const`,因此不需要限定符。
注意:您还可以通过将数组作为全局变量来实现 `static` 的效果,但我
不建议这样做。
程序堆栈溢出
如果您的数据是非静态的,并且元素数量非常大,则应使用 `std::vector`(或其他类型的堆分配内存)。
std::array<float, 1000000> a = {}
std::vector<float> v(1000000)
这是因为默认堆栈大小约为1MB,而100万个浮点数需要约4MB。堆的大小受系统可用内存(RAM)的限制。
有关堆栈和堆的更多信息在此处。
std::vector
的缺点是它比
std::array
慢一些(堆内存分配、释放和访问速度都比堆栈慢),并且它的大小不是固定的。但是,您可以将
std::vector
声明为
const
,以防止自己(或其他人)意外更改其大小或元素。
const std::vector<float> v = {...}
现在关于为什么您的
std::vector
会导致堆栈溢出有点神秘。然而,虽然
std::vector
将其元素分配在堆上,但它也在堆栈上分配指针(32位系统上为4字节,64位系统上为8字节)。因此,如果您同时拥有超过约250,000个
std::vector
,这也会导致堆栈溢出(或者64位系统上的约125,000个)。
编译器堆栈溢出
像任何程序一样,编译器也会分配内存 - 其中一些将在堆栈上。 MSVC上编译器堆栈溢出的官方错误是Fatal Error C1063。
考虑到您的调试器表现异常,我的建议是通过手动将代码拆分为模块单元并逐个编译来隔离有问题的代码。可能会有少量的代码负责该错误,例如通过递归生成大量函数来占用大量堆栈。
或者,你的代码可能因为本质上过于复杂,自然需要比栈拥有的更多的内存。在这种情况下,拆分代码仍将有益,但你也可以尝试增加MSVC的默认堆栈大小。
改进你的代码
要改进你的代码,你可以尝试将数据分成块。例如,你可以读取大约256 KB的数组,处理它,将数组写回文件,然后转移到下一个256 KB。你可以进一步选择块的大小小于L1缓存的大小(因此它可以一次性存储),这将通过最小化缓存未命中来提高性能。
注释
MSVS 2015 (update 2) produces an internal compiler error when compiling
#include "stdafx.h"
#include <array>
int main()
{
constexpr std::array<int, 1000000> a = {};
return 0;
}
The static const
variant works fine, and if I move a
outside main (making it a global variable) then it also works fine.
Not having a chkstk.asm is unusual. Mine is located at
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\i386\chkstk.asm
. If you're missing it, then maybe try reinstalling MS Visual Studio.
static const float meanTimeAO[] = { 0.4437, 0.441, 0.44206, 0.44632, 0.4508, 0.45425, ... }
吗?如果这样做,它们就不会被放在栈上。 - Cornstalks