分享
 
 
 

C++ Gotchas 条款61:检查内存分配失败的情形

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Gotcha #61: Checking for Allocation Failure

Gotcha条款61:检查内存分配失败的情形

有些问题就是不应该问,“某个内存分配动作是否成功”正属其一。

让我们来看看C++中的内存分配曾经是个什么样子。下面这段代码仔细检查了每次内存分配的成功与否:

bool error = false;

String **array = new String *[n];

if( array ) {

for( String **p = array; p < array+n; ++p ) {

String *tmp = new String;

if( tmp )

*p = tmp;

else {

error = true;

break;

}

}

}

else

error = true;

if( error )

handleError();

这种编码风格会带来许多麻烦。如果由此就可以检测出所有可能的内存分配失败的话,那或许还值得一做。非也。很不幸,String constructor本身可能会遇到内存分配错误,而且并没有什么好方法能把这个错误传出构造函数。一个可能的(但前景并不看好的)办法是,(出错时)让String constructor使String object处在某种可接受的错误状态中,并设置一个flag使其能够被该类别的用户检测到。即使假设我们可以接触String的实现代码以便实现这种行为,这种方法还是给代码的原作者以及往后所有的维护者留下了另一个需要测试的状况。

或者我们可以忽略测试。上述那样做所涉及的错误检查代码几乎不会在一开始就能完全编写正确,而且在经过一段时期的维护之后就几乎不可能是正确的了。更好的解决方法是,根本就不做检查:

String **array = new String *[n];

for( String **p = array; p < array+n; ++p )

*p = new String;

这段代码更简短、更清晰、更快捷,而且是正确的。New的标准行为就是,在分配失败事件发生时抛出一个bad_alloc exception。这让我们可以将分配失败时需要的错误处理代码封装起来,使其与余下的程序隔离开来,形成一个更干净、更清晰,一般也更有效的设计。

由于使用new时要么成功要么抛出异常,因此无论如何尝试对new的标准用法之结果进行检查都不可能测出失败:

int *ip = new int;

if( ip ) { // 条件总是为 true

// . . .

}

else {

// 永远也不会执行到这里

}

但我们可以采用operator new标准的”nothrow”版本,其会在失败时返回一个null pointer:

int *ip = new (nothrow) int;

if( ip ) { // 条件几乎总是 true

// . . .

}

else {

// 几乎不会执行到这里

}

然而,这样做又重新带回了new的老旧语义所牵涉的问题,连带着那丑恶语法引起的伤害。最好避免使用这种笨拙的向后兼容的诡异方法,直接采用能抛出异常的new进行设计和编码。

运行期系统还自动处理了分配失败时的一种特别恶劣的问题。回忆以前所提到过的,new operator实际上确立了两个函数调用:一个对operator new函数的调用,用以分配存储空间;接着是唤起构造函数,用以对分配的空间进行初始化:

Thing *tp = new Thing( arg );

如果我们捕获了一个bad_alloc exception,我们就知道出现了内存分配错误,但错误出现在哪里呢?错误可能发生在为Thing进行的存储空间原始分配动作中,也可能发生在Thing的构造函数中。在第一种情况下,我们并没有需要进行去配的内存,因为tp尚未被设为任何东西。在第二种情况下,我们就应该将tp所指向的(尚未被初始化的)内存返回给heap。然而,要我们确定是哪一种情况是很困难甚至不可能的。

幸运的是,运行期系统会为我们处理这种情况。如果为Thing进行的存储空间原始分配动作成功了,而Thing constructor失败并抛出任何异常,那么运行期系统会调用适当的operator delete(见Gotcha条款62)来归还(已分配但尚未被初始化的)存储空间。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有