您的位置:首页 > 其它

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

2010-05-11 10:18 531 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: