讨论:new抛的std::bad_alloc异常

initial:

So I use Qt a lot with my development and love it. The usual design pattern with Qt objects is to allocate them using new .

Pretty much all of the examples (especially code generated by the Qt designer) do absolutely no checking for the std::bad_alloc exception. Since the objects allocated (usually widgets and such) are small this is hardly ever a problem. After all, if you fail to allocate something like 20 bytes, odds are there's not much you can do to remedy the problem.

Currently, I've adopted a policy of wrapping "large" (anything above a page or two in size) allocations in a try/catch. If that fails, I display a message to the user, pretty much anything smaller, I'll just let the app crash with a std::bad_alloc exception.

So, I wonder what the schools of thought on this are on this?

Is it good policy to check each and every new operation? Or only ones I expect to have the potential to fail?

Also, it is clearly a whole different story when dealing with an embedded environment where resources can be much more constrained. I am asking in the context of a desktop application, but would be interested in answers involving other scenarios as well.

 

A1:

The problem is not "where to catch" but "what to do when an exception is catched".

If you want to check, instead of wrapping with try catch you'd better use

 

    #include <new>
    x
= new ( std :: nothrow ) X ();
   
if ( x == NULL ) {
       
// allocation failed
   
}

My usual practice is

  • in non interactive program, catch at main level an display an adequate error message there.

  • in program having a user interaction loop, I catch also at the loop so that the user can close some things and try to continue.

Exceptionally, there are other places where a catch is meaningful, but its rare.

 

A2 :

Handle the exception when you can . If an allocation fails, and your application can't continue without that bit of memory, why bother checking for the error?

Handle the error when it can be handled, when there is a meaningful way to recover. If there's nothing you can do about the error, just let it propagate.

 

A3:

I usually catch exceptions at the point where the user has initiated an action. For console application this means in main , for GUI applications I put handlers in places like button on-click handlers and such.

I believe that it makes little sense catching exceptions in the middle of an action, the user usually expects the operation to either succeeds or completely fail.

 

A4:

Handle it in main() (or the equivalent top level exception handler in Qt)

The reason is that std::bad_alloc either happens when you exhaust the memory space (2 or 3 GB on 32 bits systems, doesn't happen on 64 bits systems) or when you exhaust swap space. Modern heap allocators aren't tuned to run from swap space, so that will be a slow, noisy death - chances are your users will kill your app well beforehand as it's UI is no longer responding. And on Linux, the OS memory handling is so poor by default that your app is likely to be killed automatically.

So, there is little you can do. Confess you have a bug, and see if you can save any work the user may have done. To be able to do so, it's best to abort as much as possible. Yes, this may in fact lose some of the last user input. But it's that very action that likely triggered the OOM situation.. The goal is to save whatever data you can trust.

 

Practise:

just let it crash!

 

#include <iostream>

#include <cstdlib>

#include <new>

using namespace std;

void memoryEater()

{

int i = 0;

double* ptr;

while (1) {

    ptr = new double[50000000];

    cerr << ++i << '/t' ;

}

}

 

void out_of_store()

{

    cerr << "/noperator new failed: out of store/n";

    exit(1);

}

 

int main()

{

    set_new_handler(out_of_store);

    memoryEater();

    cout << "Done!" << endl;

    return 0;

}

Output:

src/newfailure> g++ setnewhandler.cpp src/newfailure> ./a.out 1 2 3 4 5 6 7 operator new failed: out of store

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值