没错,是“漫谈”,而且“漫”得有点乱。然而,抛砖尚可引玉,想到的事情,纵然脉络不是很畅,写下来也不是坏事。开卷有益,动笔也有益。
一切缘自一位C语言开发经验非常丰富的的朋友问我的一个问题。朋友问:“C++中的new在分配内存失败时会抛出异常(std::bad_alloc)而不返回0(一些老的编译器可能还在返回0,但这样的编译器实在“太老了”),这跟C程序员的做法很不一样。而且,许多C++程序在使用new创建对象时也根本不检查这种异常。这是一种什么哲学呢?”他还提到:“一般C程序员总会判断一下malloc失败的情况,就连Linux内核中都是如此。”
对于他的疑惑,我首先想到的是:一般用C++实现的应用层程序,内存管理方面自不能与内核程序相提并论。OS内核直接管理物理内存,所有应用程序的地址空间均由它映射而来,然后靠它建立机制进行翻译。内核如果在内存管理方面不保险,应用层还怎么过日子?内核中的内存分配还须考虑许多其它问题,比如不同区域的不同特性(像某些DMA使用的buffer要物理连续且位于特定位置)。同样重要的:对一个成熟的OS内核来说,即使在应用程序出现严重问题的时候也不能泄露物理内存及其它资源,且不能影响其它程序。
应用层程序则不同,它们一般拥有彼此独立的、flat的虚拟内存空间,数量上通常远大于物理内存。因此,一个应用程序如果能耗尽虚拟内存,那要么是对数据的规模估计不足,要么就是一个必需专门解决的严重bug。
耗尽虚拟内存跟其它许多严重的bug(再比如缓冲区溢出导致的堆栈破坏)一样