程序在new抛出bad_alloc之前被终止
Program gets aborted before new throws bad_alloc
下面是一个小的c++程序,在"new"抛出异常之前,它显然会在许多情况下被终止:
int main(){
try{
while(true)
new char[2];
}
catch(...){
while(true);
}
}
该程序首先使用MinGW/g++ 4.6.1编译,然后通过shell在32位Windows 7系统上执行。当时没有其他重要的程序(就内存/CPU消耗而言)正在运行。程序在进入捕获块之前终止。在Linux (Debian 7.3, gcc/c++ 4.7.2, 24GB内存)下编译和运行程序时,程序的行为类似。(在catch块中进行无限循环的原因是为了避免可能抛出异常的任何东西—特别是I/o。)当在Windows系统上两次启动程序时,发生了一些令人惊讶的事情(至少对我来说):如果程序(几乎)同时在两个不同的shell中启动,那么在抛出new-exception之前,两个进程都不会终止。同样出乎我意料的是,观察到只有适度扩大分配的内存块的大小(通过将第四行中的"2"替换为"9")才能使过早终止在Windows系统上消失。在Linux机器上,需要更大的扩展来避免终止:大约。每个块需要40,000,000字节来防止终止。
我在这里错过了什么?这是相关操作系统的正常/预期行为吗?如果是这样,这是否会削弱异常的有用性——至少在动态分配失败的情况下是这样?是否可以修改操作系统设置(由用户)以防止这种过早终止?最后,关于"严肃的"应用程序:在什么情况下(从动态内存分配开始)我不得不担心我的应用程序会被操作系统突然终止?
这是相关操作系统的正常/预期行为吗?
是的,它被称为"过度提交"或"延迟分配"。Linux(我认为是Windows,但我从未为Windows操作系统编程)会在您请求时为进程分配虚拟内存,但在您访问它之前不会尝试分配物理内存。在这个点上,如果没有可用的RAM或交换空间,程序将失败。或者,至少在Linux的情况下,其他进程可能会被随机杀死,以便您可以掠夺它们的内存。
请注意,当执行这样的小分配时,进程将分配较大的块并将它们放在堆中;因此,分配的内存通常会立即被访问。一个大的分配将直接从操作系统分配,所以你的测试程序不会访问内存-这就是为什么你观察到程序没有中止当你分配大块。
如果是这样,这是否会削弱异常的有用性——至少在动态分配失败的情况下是这样?
是的,它确实是。
是否可以修改操作系统设置(由用户)以防止这种过早终止?
在Linux上,有一个系统变量来控制超额提交策略:
echo 2 > /proc/sys/vm/overcommit_memory
值2表示永远不要过度提交——如果分配请求的内存超过当前未提交的内存加上交换空间,那么分配将失败。1意味着分配永远不会失败。0(默认值)表示猜测分配请求是否合理。
我不知道Windows是否同样可配置
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- llvm构建器向基本块添加终止符
- 如何使用隔离>终止执行来停止所有线程
- 用于将C++代码转换为 Web 程序集的脚本未终止
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 终止 QProcess 不会终止子进程
- 运行代码时,c++ 会终止进程
- 检测到堆栈粉碎:已终止 中止(核心已转储)
- 在输入句子时终止 std::out_of_range
- 二进制搜索的终止点
- MPI:检查是否有任何进程已终止
- 英特尔 TBB 程序不会终止,可能会误用参考计数器
- 如何改进我的代码,使其不会因超时而终止?(黑客排名挑战)
- while 循环不以哨兵值终止
- C++ 程序不会因为内存而终止
- 获取错误:在抛出"std::bad::alloc"的实例后终止调用 what(): std::bad_alloc