我正在编写以下程序,并且得到了std :: bad_alloc异常。
class A{
public:
int arr[5000];
A() {
for ( int i = 0; i < 5000; i++ ) {
arr[i] = 0;
}
}
};
int main() {
int cnt=0;
std::list<A*> mylist;
A *aref= NULL;
for(int i=0;i<160000;i++){
aref = new A();
mylist.push_back(aref);
}
}
我发现此错误意味着我内存不足。我想先问一下我的列表是否存储在堆中,然后为什么会出现此错误。其次,堆的最大大小是多少?
我使用-Xmx8000m在Java中运行相同的程序,并且该程序正常终止。我的RAM是16GB(如果需要的话)
答案 0 :(得分:2)
您要分配160000个A
,其中5000个int
,通常大小约为4个字节,因此您要分配160000 * 5000 * 4个字节,即/ 1024 = 3.125.000 kibiBytes和/ 1024 = 3.051,7578125 Mebibytes,大约3 GB(接近上限),这是32位进程可以获得的上限,我假设即使在运行x64 Windows时,也使用默认编译x86设置,这意味着它将在Windows中以32位兼容模式运行。加上存储在效率最低的std
容器中的160000个指针的开销,再加上分页`东西的开销,再加上可能添加的填充,就会耗尽内存。
回到您的原始问题:
A
,而只是指向它们的指针A*
,反过来,如除std
之外的任何std::array
容器都存储在堆上,即“动态存储持续时间”,但与它们指向的5000个int相比,大小没有任何区别。当您分配有new时,您的A
永远不会被清理,直到您进行删除呼叫。 C ++与Java非常不同。而且您的Java代码可能以64位进程运行,该进程知道VM所做的事情,因为它看到您将来不会使用它们。因此,如果您希望A
位于“堆栈”上,即自动存储持续时间,则可以使用std::array<A,160000>
(这是A [160000]的更好版本),但是我敢打赌这样的尺寸会使您的堆栈崩溃。 (在大多数操作系统上,每个线程大约有2MB的堆栈,但是它可能要低得多,并且调用树也需要放置)
如果您希望A
位于“堆”上,即具有动态存储持续时间,即在列表中,请使用std::list<A>
而不是std::list<A*>
并删除new
完全表达。但是,由于多种原因,最好的默认容器是std::vector<A>
,它将默认存储在一大堆“堆”内存中。
new
可以让您或更高获得所需的金额,或者它会失败,因此取决于您的运行时,即实现的含义,即操作系统和编译器,但总的来说,您可以获得的操作系统所能提供的一切,正如我所说的,x86 / 32bit进程大约为3-4GB。否则可能会更多,或者对于嵌入式应用程序,可能会少得多,直到0(根本没有动态分配)。 答案 1 :(得分:0)
std::list
被实现为双链表,节点分配在堆上。 std::list<A*> mylist
对象本身具有自动存储持续时间,它具有较小的sizeof
,但是您用mylist.push_back(aref)
添加到它的每个元素除了您new A
之外还将执行堆分配手动进行。