15

I have two questions about the new operator:

  1. Can the new operator fail to allocate memory?

  2. Should one test after every use of new, if there really was an object created?

Fabian
  • 1,982
  • 4
  • 25
  • 35
  • 3
    new never returns NULL. Even if there is no memory left to allocate. See point 3: http://stackoverflow.com/questions/240212/what-is-the-difference-between-new-delete-and-malloc-free/240308#240308 – Martin York Mar 04 '11 at 18:31
  • 1
    @Martin: what does the nothrow variant of `new` return on failure? – Jonathan Leffler Mar 04 '11 at 18:37
  • @Jonathan Leffler: That is not what this question is about. Swans in the UK are white. What about the colour of swans in Australia? When people use "nothrow new" they ask explicitly about this alternative form of new. Also its noted in the link. – Martin York Mar 04 '11 at 20:25

5 Answers5

23

operator new throws a std::bad_alloc exception on failure, unless you're explicitly using the nothrow version. Therefore, don't check the return value: If you arrive at the next line after the constructor call, you can safely assume that the constructor succeeded.

But do wrap the appropriately-scoped branch of your code in a try-catch block: Usually not right directly around the new call, but somewhere up the line where you can call off everything that depends on the allocation, and nothing else.

UPDATE: But see also Jonathan Leffler's comment below about the nothrow variant of new.

13
  1. Yes, new can fail to allocate memory, but by default it throws an exception when it does fail.
  2. You only need to check the result if you use the no-throw variant of new.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
4

No need to check for null, in general. An allocation failure will throw a std::bad_alloc exception, which you can deal with if you like.

The standard indicates:

"If an allocation function declared with a non-throwing exception-specification (15.4) fails to allocate storage, it shall return a null pointer. Any other allocation function that fails to allocate storage shall indicate failure only by throwing an exception of a type that would match a handler (15.3) of type std::bad_alloc (18.6.2.1)."

YMMV depending on how standards-compliant your compiler actually is. I think most modern c++ compilers should be embarrassed to do it differently. :)

John Watson
  • 106
  • 2
1

I don't think you should check everytime for the new Object to be created, usually new operator doesn't fails in creating the object unless you have some coding issues.

The only thing you always have to consider is to have a working constructor, which set up the new object correctly.

Emmanuel Valle
  • 332
  • 1
  • 10
1
  1. Yes. If it does fail on a modern OS with virtual memory, it's usually because of a bug in the application (e.g., allocating an insane amount of memory) or a really bad fragmentation problem.

  2. If new fails, it will throw a std::bad_alloc exception. It's up to your application to decide if it wants to catch that exception and try something else. It depends a lot on the type of application.

However, some people use a non-standard version of new that returns a null pointer instead of throwing an exception. You'd use the same criteria for that as you would for old-fashioned malloc. It depends on the type of allocation. Often, crashing is the appropriate thing to do if you cannot complete an allocation, so not checking for NULL can be an acceptable decision.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • The version of `new` that returns `0` instead of throwing is perfectly standard (as a placement new). – Ben Voigt Mar 04 '11 at 18:33
  • @Ben Voigt: That's true, but I was referring to older tricks, like linking with a non-standard library or using a compiler switch that turns all `new`s into `new(std::nothrow)`. – Adrian McCarthy Mar 04 '11 at 18:38
  • @Ben: a placement `new` is told what address to use; under what circumstances is it going to fail? Programmer error? Anything else? – Jonathan Leffler Mar 04 '11 at 18:39
  • @Jonathan: No. Any `operator new` that accepts arguments beyond just the size (and specifically the new that accepts `std::nothrow_t` as an argument) is called *placement-new*. You're referring to the standard-provided new which accepts an address, but that's just one of several possible placement-new signatures provided in the standard (and then user code can add other signatured). – Ben Voigt Mar 04 '11 at 18:41