Can the C++ `new` operator ever throw an exception

2019-03-08 09:45发布

Can the new operator throw an exception in real life?

And if so, do I have any options for handling such an exception apart from killing my application?

Update:

Do any real-world, new-heavy applications check for failure and recover when there is no memory?


See also:

18条回答
ゆ 、 Hurt°
2楼-- · 2019-03-08 10:33

In many cases there's no reasonable recovery for an out of memory situation, in which case it's probably perfectly reasonable to let the application terminate. You might want to catch the exception at a high level to display a nicer error message than the compiler might give by default, but you might have to play some tricks to get even that to work (since the process is likely to be very low on resources at that point).

Unless you have a special situation that can be handled and recovered, there's probably no reason to spend a lot of effort trying to handle the exception.

查看更多
Ridiculous、
3楼-- · 2019-03-08 10:35

It depends on the compiler/runtime and on the operator new that you are using (e.g. certain versions of Visual Studio will not throw out of the box, but would rather return a NULL pointer a la malloc instead.)

You can always catch a std::bad_alloc exception, or explicitly use nothrow new to return NULL instead of throwing. (Also see past StackOverflow posts revolving around the subject.)

Note that operator new, like malloc, will fail when you have run out of memory, out of address space (e.g. 2-3GB in a 32-bit process depending on the OS), out of quota (ulimit was already mentioned) or out of contiguous address space (e.g. fragmented heap.)

查看更多
成全新的幸福
4楼-- · 2019-03-08 10:35

Note that in Windows, very large new/mallocs will just allocate from virtual memory. In practice, your machine will crash before you see that exception.

char *pCrashMyMachine = new char[TWO_GIGABYTES];

Try it if you dare!

查看更多
【Aperson】
5楼-- · 2019-03-08 10:37

osgx said:

Does any real-world applications checks a lot number of news and can recover when there is no memory?

I have answered this previously in my answer to this question, which is quoted below:

It is very difficult to handle this sort of situation. You may want to return a meaningful error to the user of your application, but if it's a problem caused by lack of memory, you may not even be able to afford the memory to allocate the error message. It's a bit of a catch-22 situation really.

There is a defensive programming technique (sometimes called a memory parachute or rainy day fund) where you allocate a chunk of memory when your application starts. When you then handle the bad_alloc exception, you free this memory up, and use the available memory to close down the application gracefully, including displaying a meaningful error to the user. This is much better than crashing :)

查看更多
趁早两清
6楼-- · 2019-03-08 10:42

I use Mac OS X, and I've never seen malloc return NULL (which would imply an exception from new in C++). The machine bogs down, does its best to allocate dwindling memory to processes, and finally sends SIGSTOP and invites the user to kill processes rather than have them deal with allocation failure.

However, that's just one platform. CERTAINLY there are platforms where the default allocator does throw. And, as Chris says, ulimit may introduce an artificial constraint so that an exception would be the expected behavior.

Also, there are allocators besides the default one/malloc. If a class overrides operator new, you use custom arguments to new(…), or you pass an allocator object into a container, it probably defines its own conditions to throw bad_alloc.

查看更多
Melony?
7楼-- · 2019-03-08 10:42

The new-handler function is the function called by allocation functions whenever new attempt to allocate the memory fails. We can have our own logging or some special action, eg,g arranging for more memory etc. Its intended purpose is one of three things: 1) make more memory available 2) terminate the program (e.g. by calling std::terminate) 3) throw exception of type std::bad_alloc or derived from std::bad_alloc. The default implementation throws std::bad_alloc. The user can have his own new-handler, which may offer behavior different than the default one. THis should be use only when you really need. See the example for more clarification and default behaviour,

#include <iostream>
#include <new>

void handler()
{
    std::cout << "Memory allocation failed, terminating\n";
    std::set_new_handler(nullptr);
}

int main()
{
    std::set_new_handler(handler);
    try {
        while (true) {
            new int[100000000ul];
        }
    } catch (const std::bad_alloc& e) {
        std::cout << e.what() << '\n';
    }
}
查看更多
登录 后发表回答