How to check memory allocation failures with new operator?

前端 未结 4 1117
囚心锁ツ
囚心锁ツ 2020-12-03 10:16

Just recently I switched the language of my project to use C++ from C. With C, I used malloc and after that I check if malloc was successful but with C++, I use \'new\' to a

相关标签:
4条回答
  • 2020-12-03 10:45

    Well, you call new that throws bad_alloc, so you must catch it:

    try
    {
        scoped_array<char> buf(new char[MAX_BUF]);
        ...
    }
    catch(std::bad_alloc&) 
    {
        ...
    }
    

    or

    scoped_array<char> buf(new(nothrow) char[MAX_BUF]);
    if(!buf)
    {
       //allocation failed
    }
    

    What I mean by my answer is that smart pointers propagate exceptions. So if you're allocating memory with ordinary throwing new, you must catch an exception. If you're allocating with a nothrow new, then you must check for nullptr. In any case, smart pointers don't add anything to this logic

    0 讨论(0)
  • 2020-12-03 10:45

    In C++ there are 2 primary ways in which new allocates memory and each requires different error checking.

    The standard new operator will throw a std::bad_alloc exception on failure and this can be handled like a normal exception

    try {
      char* c = new char[100];
    } catch (std::bad_alloc&) {
      // Handle error
    }
    

    Or alternative the nothrow version of new will simply return NULL on failure

    char* c = new (std::nothrow) char[100];
    if (!c) {
      // Handle error
    }
    

    I'm curious though as to what you expect to do when the allocation fails? If there is no memory available to allocate your object, there's often very little which can be done in the process.

    0 讨论(0)
  • 2020-12-03 10:48

    I hate to say it, but IMO, you're going in the wrong direction (and, unfortunately, the other answers you've gotten haven't really pointed you in the right direction either).

    Rather than choosing between different varieties of smart pointer and/or normal vs. nothrow variants of new, you should probably take at least two more steps back from what you're doing, and replace your manually-managed dynamic data structures with collections. This may not always be the right choice, but at least in my experience, it's the right way to go a lot more often than not. The standard library has a number of possibilities (vector, deque, list, set, etc.), and chances are pretty good that you can use one of them rather than dealing directly with new and company at all.

    By default, those will use an allocator that ends up using the normal (throwing) variant of new. You, therefore, normally want to put most code in a try block at a fairly high level, and have a catch clause that deals with having run out of memory there.

    When/if you do need to deal with allocating memory directly, chances are pretty good that you still want to provide an interface similar to that of the standard containers in the library so it'll work with the normal algorithms and iterators. Your initial experience using the existing containers will pay of well when you get to this point, even though it may be a ways down the road.

    0 讨论(0)
  • 2020-12-03 10:48

    You'll still need to check for a memory allocation failure.

    Either

    scoped_array<char> buf;
    
    try {
      buf.reset( new char[MAX_BUF] );
    } catch( std::bad_alloc& ) {
      // Handle the failure
    }
    

    Or

    scoped_array<char> buf( new(std::nothrow)char[MAX_BUF] );
    
    if( buf.get() == NULL ) {
       // Handle the failure
    }
    
    0 讨论(0)
提交回复
热议问题