How often do you check for an exception in a C++ n

2020-02-08 20:03发布

I just started reading Effective C++ today and got to the point where the author talks about the operator new.

The book explains very well how you can catch (with various degrees of elegance) the std::bad_alloc exception that the operator new can raise if you run out of memory.

My question is: How often do you check for the case when there isn't enough memory to instantiate a object, if at all? and why? Is it worth the hassle?

标签: c++ exception
10条回答
不美不萌又怎样
2楼-- · 2020-02-08 20:40

I catch exceptions when I can answer this question:

What will you do with the exception once you've caught it?

Most of the time, my answer is, "I have no idea. Maybe my caller knows." So I don't catch the exception. Let it bubble up to someone who knows better.

When you catch an exception and let your function proceed running, you've said to your program, "Never mind. Everything's fine here." When you say that, by golly, everything had better be fine. So, if you've run out of memory, then after you've handled std::bad_alloc, you should not be out of memory anymore. You shouldn't just return an error code from your function, because then the caller has to check explicitly for that error code, and you're still out of memory. Your handling of that exception should free some memory. Empty some caches, commit some things to disk, etc. But how many of the functions in your program do you really want to be responsible for reducing your program's memory usage?

If you cannot solve the problem that triggered the exception, then do not handle the exception.

查看更多
贪生不怕死
3楼-- · 2020-02-08 20:43

If you have to allocate memory for e.g. a path buffer where you know it will be only a few bytes, that may not be worth the hassle.

But when you have to allocate memory for bigger objects like images or files, you definitely should do the check.

查看更多
做自己的国王
4楼-- · 2020-02-08 20:46

Not handling the exception will crash your program, and the support requests you get will be somewhere between "does not work", "crashes randomly", and "I lost all my work of that day". If you think that's ok, then it's not worth the hassle indeed.

The least you can do is telling the user that he actually ran out of memory indeed, at least giving him (or support) a clue why the application is randomly crashing.

Additionally, you can try to preserve results, e.g. saving them to a recovery file. That might be easier to do before you run into the problem, though.

It would be fabulous if you could go as far as giving an error message like "You cannot insert this image because you ran out of memory". And you'd continue working as if nothing happened. However, this would mean all the code behind a user command must be transactional and give a strong exception safety guarantee.


So, identify the cost of randomly running out of memory. Based on that, evaluate which "level of protection" you need to give to your user.

查看更多
疯言疯语
5楼-- · 2020-02-08 20:48

In a system using virtual memory, malloc() won't return NULL, and new won't return std::bad_alloc; they will return a virtual address. When you write to the memory zone pointed by this address, the system will try to map the virtual address to a physical address. If there's no more memory available, you'll get a page fault.

So you catch for std::bad_alloc when you're on an embedded system without MMU, and hope you can do something to free some memory.

查看更多
smile是对你的礼貌
6楼-- · 2020-02-08 20:55

I think this largely depends on the type of applications you write. If i would write something that doesn't affect the global stability of the system, let's say a game or a movie player, i would not check for that exception. My application would call std::terminate and i could log it somewhere, or my kernel would kill my program first to make room for other programs.

If i write a program whose stability directly corresponds with the one of the system it runs on, let's say a video driver or an init system, i would check for memory exceptions all the time (probably wrapping allocations in a function), and get some memory from a pre-allocated pool in case of an allocation failure.

I think this all depends on proportionality. What do you gain from a amazingly stable movie player, if it starts slowing down to play movies because of your aggressive checking?

Btw, someone answered malloc won't return 0 when you're out of memory for some systems. That's right, but as the manpage of malloc points out (linux specific)

In case Linux is employed under circumstances where it would be less desirable to suddenly lose some randomly picked processes, and moreover the kernel version is sufficiently recent, one can switch off this overcommitting behavior using a command like: $ echo 2 > /proc/sys/vm/overcommit_memory

See also the kernel Documentation directory, files vm/overcommit-accounting and sysctl/vm.txt.

查看更多
成全新的幸福
7楼-- · 2020-02-08 20:56

Never. I have always considered that the default behaviour (there is a std::bad_alloc exception, it is not handled, and thus the program terminates with an error message) is good, for the applications I've worked in.

查看更多
登录 后发表回答