在 Stack 上声明大数组
Posted
技术标签:
【中文标题】在 Stack 上声明大数组【英文标题】:Declare large array on Stack 【发布时间】:2013-06-06 10:48:50 【问题描述】:我正在使用 Dev C++ 编写一个模拟程序。为此,我需要声明一个数据类型为double
的一维数组。它包含4200000
元素——比如double n[4200000]
。
编译器没有显示错误,但程序在执行时退出。我已经检查过了,程序对于具有5000
元素的数组执行得很好。
现在,我知道不建议在堆栈上声明这么大的数组。然而,问题是模拟需要我多次调用数组中的特定元素 - 例如,对于给定的计算,我可能需要 n[234]
或 n[46664]
的值。因此,我需要一个更容易筛选元素的数组。
有没有办法可以在堆栈上声明这个数组?
【问题讨论】:
对于 Linux/gcc,请参见 ***.com/questions/2279052/…,对于 Windows/gcc,请参见 ***.com/questions/156510/…,对于 MSVC,请参见 msdn.microsoft.com/en-us/library/tdkhxaks%28v=vs.110%29.aspx - 参见此处。 我不认为你可以使用std::vector<double> ar(4200000);
吗?其余的仅使用常规数组白话进行索引等。
完全不清楚为什么这个数组需要在堆栈上。当您从堆中分配它时,它也能正常工作。
对于 Visual Studio:visual studio - Increase stack size in c++ - Stack Overflow
【参考方案1】:
不,没有(我们会说“合理”)在堆栈上声明这个数组的方法。但是,您可以在堆栈上声明指针,并在堆上留出一点内存。
double *n = new double[4200000];
访问其中的 n[234] 应该不会比访问您声明的数组的 n[234] 快:
double n[500];
或者更好的是,你可以使用向量
std::vector<int> someElements(4200000);
someElements[234];//Is equally fast as our n[234] from other examples, if you optimize (-O3) and the difference on small programs is negligible if you don't(+5%)
如果使用 -O3 进行优化,它与数组一样快,而且更安全。与
一样double *n = new double[4200000];
除非你这样做,否则你会泄漏内存:
delete[] n;
除了例外和各种各样的事情,这是一种非常不安全的做事方式。
【讨论】:
这是一个非常好的答案!使用第一种方法,有没有什么快速或默认的方式将所有初始化为零? 将其设为全局变量是另一种选择,但全局变量通常被认为是不好的做法。 @xiaohuamao 这应该在一个新问题中提出;但是已经有一个c++ - Allocated array already zeroed - Stack Overflow【参考方案2】:你有什么理由特别想要这个堆栈吗?
我之所以问,是因为以下内容将为您提供一个可以以类似方式使用的构造(尤其是使用 array[index]
访问值),但它的大小限制要少得多(总最大大小取决于 32 位/ 64 位内存模型和可用内存(RAM 和交换内存)),因为它是从堆中分配的。
int arraysize= 4200000;
int *heaparray= new int[arraysize];
...
k= heaparray[456];
...
delete [] heaparray;
return;
【讨论】:
我会将可用内存切换到可用内存,因为页面文件/交换空间也应该计算在内。 @MM 我只是像这里的每个人一样采用通常的方式:快速做出一个异想天开的答案,然后编辑它以制作 cmets,因为我经常会立即做出一个很好的答案并得到三个快速回答排在前面。【参考方案3】:是的,你可以在堆栈上声明这个数组(需要做一些额外的工作),但这并不明智。
数组必须存在于堆栈中没有正当理由。
一次动态分配单个数组的开销可以忽略不计(您可以说“零”),如果您担心的话,智能指针将安全地处理不泄漏内存。 堆栈分配的内存与堆分配的内存没有任何不同(除了一些对小对象的缓存效果,但这些不适用于此处)。
到此为止,不要这样做。
如果您坚持必须在堆栈上分配数组,则首先需要保留 32 兆字节的堆栈空间(最好多一点)。为此,使用 Dev-C++(假定为 Windows+MingW),您将需要使用诸如-Wl,--stack,34000000
之类的编译器标志为您的可执行文件设置保留的堆栈大小(这会保留多于 32MiB),或者创建一个线程(其中允许您为该线程指定保留的堆栈大小)。
但真的,再次,不要那样做。动态分配一个巨大的数组没有错。
【讨论】:
求知欲,想看看这个方法。如果您不想在这里提供它(以免给某人他们还没有准备好使用的工具),您可以开始与我聊天!或者只是发送一个指向正确方向的谷歌短语。 啊,编译器标志...这是作弊! :) 虽然,我认为如果您使用线程,您实际上也可以在代码中执行此操作...... @ChrisCM: 是的,如果你为此创建一个线程,你可以纯粹以编程方式完成......但与使用operator new[]
相比简直是疯了,这只是 制作 用于此类任务。【参考方案4】:
您可以增加堆栈大小。尝试将这些选项添加到您的链接标志中:
-Wl,--stack,36000000
虽然它可能太大(我不确定 Windows 是否对堆栈大小设置了上限。)但实际上,即使它有效,您也不应该这样做。正如其他答案中所指出的那样,使用动态内存分配。
(奇怪,写了一个答案并希望它不会被接受...... :-P)
【讨论】:
+1 最后一句!拜托,看在上帝的份上,如果你不明白为什么新的或基于向量的解决方案与静态分配的数组一样好,就盲目地使用它们,忘记这篇文章的存在吧!以上是关于在 Stack 上声明大数组的主要内容,如果未能解决你的问题,请参考以下文章