C++内存分配失败处理程序在不同Ubuntu版本行为差异求助
我是C新手,跟随《Thinking in C》编写了一段设置new handler处理内存分配失败的代码。在我的Ubuntu 22.04LTS笔记本上,程序未触发void out_of_memory定义的预期错误输出,仅显示“Killed”;但在Ubuntu 18.04LTS服务器上,程序能正常输出“memory exhausted after 8946078 allocations!”。请问为何两台系统上程序行为不同?
测试代码
// Changing the new-handler #include <iostream> #include <cstdlib> #include <new> using namespace std; int count = 0; void out_of_memory() { cerr << "memory exhausted after " << count << " allocations!" << endl; exit(1); } int main() { set_new_handler(out_of_memory); while(1) { count++; new int[1000]; // Exhausts memory } }
不同系统输出
Ubuntu 22.04 LTS笔记本输出
Killed
Ubuntu 18.04 LTS服务器输出
memory exhausted after 8946078 allocations!
原因分析
核心差异源于Linux内核的**OOM Killer(内存不足终止器)**行为和内存分配策略的版本变化:
OOM Killer触发时机不同:Ubuntu 22.04搭载的内核版本更高,OOM Killer的触发逻辑更激进。当程序快速循环申请内存时,系统会更早判定该进程占用过多资源,直接终止进程,完全没等到
new运算符分配失败、触发new handler的时机。而Ubuntu 18.04的内核OOM Killer触发阈值更高,程序有机会耗尽系统内存(含交换空间),让new分配失败,从而执行定义的out_of_memory函数。内存过度分配策略的影响:Linux默认允许进程申请比实际可用内存更多的空间(过度分配),但仅在进程真正使用内存时才分配物理页。新版本系统在内存接近耗尽时,会更快触发OOM Killer回收资源;旧版本则会让进程继续尝试分配,直到物理内存+交换空间完全耗尽,才会让
new返回分配失败。内存申请速度的影响:代码每次申请4KB内存(1000个int),循环速度极快。新版本系统的内存监控机制更灵敏,在
new还没来得及返回失败状态前,就已经启动OOM Killer终止了进程。
内容的提问来源于stack exchange,提问作者Yiwei Jiang

