int *p;
while(true)
{
p = new int;
}
由于内存空间不足,此代码不应该崩溃。我已经尝试打印出p的值,即p的内存地址,它似乎增加但没有崩溃。
为什么会这样?
答案 0 :(得分:9)
这种解决方案就像试图在驾驶1MPH时在街道上的电线杆上撞车。它最终会发生,但如果你想要快速的结果,你需要提高速度。
int *p;
while (true) {
p = new int[1024*1024*1024];
}
我的回答是基于您的代码库使用标准STL分配器,该分配器会导致内存分配失败。还有其他可用的分配器只在失败的分配上返回NULL
。这种类型的分配器永远不会在此代码中崩溃,因为失败的分配不被认为是致命的。您必须检查NULL
分配的返回情况,以便检测错误。
另一个警告,如果你在64位系统上运行,由于地址空间的大小增加,这可能需要相当长的时间才能崩溃。它不是在街上进行电话调查,而是在全国各地。
答案 1 :(得分:9)
在您看到崩溃之前,您似乎不会关闭此问题:)
在类Unix操作系统上,您可以使用ulimit命令限制进程可用的虚拟内存量。通过将VM设置为1MB,我能够在大约5秒钟内看到所需的结果:
$ ulimit -v $((1024*1024)) # set max VM available to process to 1 MB
$ ulimit -v # check it.
1048576
$ time ./a.out # time your executable.
terminate called after throwing an instance of 'St9bad_alloc'
what(): std::bad_alloc
Aborted
real 0m5.502s
user 0m4.240s
sys 0m1.108s
答案 2 :(得分:7)
小块内存的几个分配比一个大分配慢。例如,它需要更多的时间来分配4个字节100万次,而不是1百万个字节4次。
尝试一次分配更大的内存块:
int *p;
while(true)
{
p = new int[1024*1024];
}
答案 3 :(得分:4)
你没等多久。
[如果你想看看它是如何进展的,可以在每1000000个循环上添加一些输出,或类似的东西。 最终会失败。]
答案 4 :(得分:1)
我认为编译器正在进行一些优化,并没有真正分配内存。 我运行上面的例子(使用valgrind)一些,并看到即使有分配,所有0字节内存。
尝试这个,你的程序将被杀死(至少在unix上):
#include <cstdio>
int main() {
int *p;
while (true) {
p = new int[1024*1024];
p[0] = 0;
printf("%p\n",p);
for(unsigned j = 1; j < 1024*1024; j++) {
p[j] = p[j-1] + 1;
}
}
return 0;
}
你看到唯一的区别是我使用分配的内存。
所以,它并没有真正崩溃,因为我猜操作系统只是通过杀死它来阻止进程崩溃(不是100%肯定这个)
答案 5 :(得分:1)
另一种可能性:大多数操作系统将执行乐观分配。当你使用malloc,比如500 MB时,在程序实际尝试读取或写入内存之前,实际上可能不会保留该内存。
Linux尤其因过度使用内存而臭名昭着,然后依靠OOM(内存不足)杀手来打击试图收集内核承诺的进程。