漫谈C++内存分配失败

本文探讨了C++中new操作符在内存分配失败时抛出异常的哲学,对比了C语言和Java的处理方式。文章指出,应用程序耗尽虚拟内存通常是严重问题的标志,快速失败比隐藏问题更好。同时,异常处理机制使得代码更简洁,责任更清晰。此外,还介绍了nothrow new和set_new_handler等处理内存分配失败的方法。

没错,是“漫谈”,而且“漫”得有点乱。然而,抛砖尚可引玉,想到的事情,纵然脉络不是很畅,写下来也不是坏事。开卷有益,动笔也有益。

 

一切缘自一位C语言开发经验非常丰富的的朋友问我的一个问题。朋友问:“C++中的new在分配内存失败时会抛出异常(std::bad_alloc)而不返回0(一些老的编译器可能还在返回0,但这样的编译器实在“太老了”),这跟C程序员的做法很不一样。而且,许多C++程序在使用new创建对象时也根本不检查这种异常。这是一种什么哲学呢?”他还提到:“一般C程序员总会判断一下malloc失败的情况,就连Linux内核中都是如此。”

 

对于他的疑惑,我首先想到的是:一般用C++实现的应用层程序,内存管理方面自不能与内核程序相提并论。OS内核直接管理物理内存,所有应用程序的地址空间均由它映射而来,然后靠它建立机制进行翻译。内核如果在内存管理方面不保险,应用层还怎么过日子?内核中的内存分配还须考虑许多其它问题,比如不同区域的不同特性(像某些DMA使用的buffer要物理连续且位于特定位置)。同样重要的:对一个成熟的OS内核来说,即使在应用程序出现严重问题的时候也不能泄露物理内存及其它资源,且不能影响其它程序。

应用层程序则不同,它们一般拥有彼此独立的、flat的虚拟内存空间,数量上通常远大于物理内存。因此,一个应用程序如果能耗尽虚拟内存,那要么是对数据的规模估计不足,要么就是一个必需专门解决的严重bug。
耗尽虚拟内存跟其它许多严重的bug(再比如缓冲区溢出导致的堆栈破坏)一样,多数情况下即使能检测到也常常无计可施,如果“有计可施”,那何不早施此计?何苦等它发生再亡羊补牢呢?反过来想,该失败的时候痛痛快快的快速失败,这不算坏事。至少,比带着问题继续运行半小时,然后在某个完全不相干的地方发生莫名其妙又难以重现的bug要好得多。
这是我当时给朋友的回答,朋友勉强同意了,至少不再纠结C++程序员因何不在new的时候检查std::bad_alloc了。然而,顺着这个问题,我觉得可以联想到好多相关的话题。

 

(1)首先想到的是Java语言的做法。Java中的变量都是引用(基本类型的除外),而被引用

评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值