Can the C++ `new` operator ever throw an exception in real life?

前端 未结 18 1816
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 08:40

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?

相关标签:
18条回答
  • 2021-01-30 09:15

    In Unix systems, it's customary to run long-running processes with memory limits (using ulimit) so that it doesn't eat up all of a system's memory. If your program hits that limit, you will get std::bad_alloc.


    Update for OP's edit: the most typical case of programs recovering from an out-of-memory condition is in garbage-collected systems, which then performs a GC and continues. Though, this sort of on-demand GC is really for last-ditch efforts only; usually, good programs try to GC periodically to reduce stress on the collector.

    It's less usual for non-GC programs to recover from out-of-memory issues, but for Internet-facing servers, one way to recover is to simply reject the request that's causing the memory to run out with a "temporary" error. ("First in, first served" strategy.)

    0 讨论(0)
  • 2021-01-30 09:17

    Yes, new can and will throw if allocation fails. This can happen if you run out of memory or you try to allocate a block of memory too large.

    You can catch the std::bad_alloc exception and handle it appropriately. Sometimes this makes sense, other times (read: most of the time) it doesn't. If, for example, you were trying to allocate a huge buffer but could work with less space, you could try allocating successively smaller blocks.

    0 讨论(0)
  • 2021-01-30 09:18

    Yes, new can throw std::bad_alloc (a subclass of std::exception), which you may catch.

    If you absolutely want to avoid this exception, and instead are ready to test the result of new for a null pointer, you may add a nothrow argument:

    T* p = new (nothrow) T(...);
    if (p == 0)
    {
        // Do something about the bad allocation!
    }
    else
    {
        // Here you may use p.
    }
    
    0 讨论(0)
  • 2021-01-30 09:18

    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';
        }
    }
    
    0 讨论(0)
  • 2021-01-30 09:19

    Yes new will throw an exception if there is no more memory available, but that doesn't mean you should wrap every new in a try ... catch. Only catch the exception if your program can actually do something about it.

    If the program cannot do anything to handle that exceptional situation, what is often the case if you run out of memory, there is no use in catching the exception. If the only thing you could reasonably do is to abort the program you can as well just let the exception bubble up to top level, where it will terminate the program as well.

    0 讨论(0)
  • 2021-01-30 09:22

    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.

    0 讨论(0)
提交回复
热议问题