程序在新抛出bad_alloc之前中止

时间:2014-08-18 15:06:32

标签: c++ operating-system

下面是一个小型的C ++程序,显然会在很多情况下在#34; new"之前被中止。抛出异常:

int main(){
   try{
      while(true)
         new char[2];
   }
   catch(...){
      while(true);
   }
}

该程序首先使用MinGW / g ++ 4.6.1编译,然后通过shell在32位Windows 7系统上执行。当时没有运行严肃的其他程序(在内存/ CPU消耗方面)。程序在进入catch-block之前终止。在Linux(Debian 7.3,gcc / c ++ 4.7.2,24GB内存)下编译和运行程序时,程序表现相似。 (catch块中无限循环的原因是为了避免任何可能抛出异常的东西 - 尤其是I / O.) 在Windows系统上启动程序两次时发生了令人惊讶的事情(至少对我来说):如果程序是在两个不同的shell(几乎)同时启动的话,那么两个进程都不会在抛出新异常之前终止。 同样令我意外的是观察到只有适度扩大分配的内存块的大小(通过用" 9&#34替换" 2"第四行)使得提前终止在Windows系统上消失。在Linux机器上需要更大幅度的扩大以避免终止:大约。每个块需要40,000,000个字节才能防止终止。

我在这里缺少什么?这是涉及的操作系统的正常/预期行为吗?如果是这样,这是否会破坏例外的有用性 - 至少在动态分配失败的情况下?可以以某种方式(由用户)修改OS设置以防止这种过早终止吗?最后,关于"认真的"应用程序:在什么时候(例如动态内存分配),我不得不担心我的应用程序被操作系统突然中止?

1 个答案:

答案 0 :(得分:3)

  

这是涉及的操作系统的正常/预期行为吗?

是的,它被称为“过度使用”或“懒惰分配”。 Linux(我认为Windows,但我从不为该操作系统编程)会在您请求时为进程分配虚拟内存,但在您访问它之前不会尝试分配物理内存。这就是,如果没有可用的RAM或交换空间,程序将失败。或者,至少在Linux的情况下,其他进程可能会被随机杀死,因此您可以掠夺他们的记忆。

请注意,在进行这样的小分配时,进程会分配较大的块并将它们放在堆中;所以通常会立即访问分配的内存。大型分配将直接从操作系统中分配,因此您的测试程序将无法访问该内存 - 这就是为什么您在分配大块时发现程序没有中止的原因。

  

如果是这样,这是否会破坏例外的有用性 - 至少在动态分配失败的情况下?

是的,确实如此。

  

可以以某种方式(由用户)修改操作系统设置以防止这种过早终止吗?

在Linux上,有一个系统变量来控制过度使用政策:

echo 2 > /proc/sys/vm/overcommit_memory

值2意味着永远不会过度使用 - 如果分配要求的数量超过当前未提交的RAM加交换,则分配将失败。 1意味着永远不会失败。 0(默认值)表示猜测分配请求是否合理。

我不知道Windows是否可以配置。