我正在编写以下程序,我得到 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);
}
}
我发现这个错误意味着我的内存不足。我想首先询问我的 List 是否存储在堆中然后我为什么会收到此错误。第二个堆最大大小是多少?
我使用-Xmx8000m 在 Java 中运行相同的程序,它正常终止。我的 RAM 是 16GB(如果这很重要)
2 回答
您正在分配 160000 个
A
,其中包含 5000int
,通常大小约为 4 个字节,因此您分配的是 160000 * 5000 * 4 个字节,其中/1024 = 3.125.000 kibiBytes 和/1024 = 3.051,7578125 Mebibytes 所以大约 3 个 GB,接近上限,32-bit 进程可以得到什么,我认为,即使在运行 x64 窗口时,你使用默认的 x86 设置编译它,这意味着它将在 Windows 中以 32 位兼容模式运行。添加你存储在效率最低的std
容器中的 160000 指针的开销,加上分页的东西,加上可能添加的填充,你内存不足。要回到原来的问题:
A
只是指向它们的指针A*
s,反过来,就像在任何std
容器中一样,除了std::array
存储在堆上,i.e。 “动态存储持续时间”,但它们的大小与它们指向的 5000 英寸不相上下。当您使用 new 分配时,您的A
永远不会被清除,直到您通过删除调用。 C 与 Java 非常不同。而你的 Java 代码可能是一个 64 位进程,它知道 VM 做了什么,因为它看到你将来不会使用它们。所以,如果你想让你的
A
在“堆栈”i.e 上。自动存储持续时间,你可以使用std::array<A,160000>
(这是一个更好的 A [11]版本),但我打赌你会崩溃堆叠这样的大小。 (在大多数操作系统上,每个线程可以获得大约 2MB 的堆栈,但它可以低得多,并且您的调用树也需要放置)如果你想在“堆”i.e 上你的
A
。具有动态存储持续时间,i.e。在列表中,使用std::list<A>
而不是std::list<A*>
并完全删除new
表达式。但是由于多种原因,最好的默认容器是std::vector<A>
,它会将它们存储在一大块“堆”内存中。new
要么获得请求的数量或更多,要么失败,所以它取决于你的运行时 i.e。实现意味着操作系统和编译器,但一般来说,你可以获得操作系统给你的程度,正如我所说的那样 3-4GB 为 x86/32bit 进程。否则它可以更多,或者在嵌入式应用程序的情况下,非常少于 0(根本没有动态分配)。std::list
实现为双向链表,在堆上分配节点。std::list<A*> mylist
对象本身具有自动存储持续时间,它有一个小的sizeof
,但是除了你手动执行的new A
之外,你用mylist.push_back(aref)
添加的每个元素都将执行堆分配。