不应该这个代码崩溃

时间:2010-10-25 17:46:06

标签: c++ dynamic-memory-allocation new-operator

int *p;
while(true)
{
 p = new int;
}

由于内存空间不足,此代码不应该崩溃。我已经尝试打印出p的值,即p的内存地址,它似乎增加但没有崩溃。

为什么会这样?

6 个答案:

答案 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(内存不足)杀手来打击试图收集内核承诺的进程。