我有一个从大型数组中读取数据的程序,我最初在Visual Studio中将该程序划分为两个单独的项目,每个项目都工作得很好,但当我试图将它们放在一起时,程序表现得很奇怪,在调试时跳过了一些步骤。我对C++非常陌生,所以我开始做一些研究,我发现也许我是在用那些巨大的数组来填充堆栈,我应该试着把它们放到堆上。
我决定更改std::vector
的每个数组,并以这种方式初始化它们:
std::vector<double> meanTimeAO = { 0.4437, 0.441, 0.44206, 0.44632, 0.4508, 0.45425,...}
但是现在当我尝试编译编译器崩溃时,当我尝试编译堆栈溢出时更改了所有的数组后,我认为我通过将数组更改为向量来释放堆栈中的内存空间,但似乎我得到了相反的结果,为什么呢?
我该如何处理这些大数组呢?(它们是固定的,不会改变值或大小)
发布于 2016-05-25 15:59:56
正如@Ajay的回答和@Cornstalks注释正确指出的那样,通过在数组上使用static
或constexpr
限定符,可以完全避免堆栈和堆
const static std::array<float, 1000000> a1 = {}; // OK
constexpr std::array<float, 1000000> a2 = {}; // OK in C++11 onwards
这会将数组存储在内存的data initialized部分(good explanation here)。const
仅用于禁止修改a1
,并不是避免堆栈溢出所必需的。声明为constexpr
的变量也会自动为const
,因此不需要限定符。
注意:您也可以通过使数组成为全局变量来实现static
的效果,尽管我不建议这样做。
程序堆栈溢出
如果您的数据是非静态的,那么当元素数量非常大时,您应该使用std::vector
(或其他类型的堆分配的内存)。
std::array<float, 1000000> a = {}; // Causes stack-overflow on 32-bit MSVS 2015
std::vector<float> v(1000000); // OK
这是因为默认堆栈大小约为1MB,100万个浮点数需要约4MB。堆的大小受系统可用内存(RAM)的限制。More on the stack and heap here。
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。
鉴于您的调试器行为异常,我的建议是尝试通过手动将代码拆分成模块化单元并单独编译来隔离有问题的代码。有可能是因为少量的代码消耗了大量的堆栈,例如通过递归生成大量的函数。
或者,您的代码可能本质上非常复杂,因此它自然需要比堆栈拥有的内存更多的内存。在这种情况下,拆分代码仍然是有好处的,但您也可以尝试使用increasing the default stack size of MSVC。
改进你的代码
为了改进你的代码,你可以试着把你的数据分成块。例如,您可以:读入大约256KB的数组,处理它,将数组写回文件,然后移到下一个256KB。您可以进一步选择块的大小小于L1缓存的大小(以便可以一次存储所有数据),这将通过最小化缓存未命中来提高性能。
备注
#include "stdafx.h“#include int main() { constexpr std::array a= {};return 0;}
static const
变体运行得很好,如果我将a
移出main (使其成为全局变量),那么它也会运行得很好。
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\i386\chkstk.asm
。如果你错过了它,也许可以尝试重新安装MS Visual Studio.发布于 2016-05-25 13:07:13
如果数组的大小是固定的,并且它的元素没有变化,那么实际上就没有必要使用vector
。您可以使用std::array
、const
的数组或constexpr
。
constexpr float meanTimeAO[] = { 0.4437f, 0.441f, 0.44206f, 0.44632f, 0.4508f, 0.45425f,...}
发布于 2016-05-25 18:44:35
指出上述答案中可能忽略的几个问题:
建议:您可以尝试查看您正在使用的编译器版本中是否有任何已知的错误(即查看您的编译器供应商是否发布了可能解决编译器崩溃问题的更新版本)。
此外,特别要注意“它们永远不会改变值或大小”的注释,尝试将数据放入静态常量双数组,而不是std::vectors (甚至是链表)中。一个不变的静态分配的只读链表是一种浪费时间的行为,而你可能只应该使用double[]。静态常量数据在编译/链接时初始化,而不是在运行时初始化,并且存在于它自己的内存区(严格地说,既不是堆栈也不是堆)。
https://stackoverflow.com/questions/37427967
复制相似问题