New in VS 2015: /Zc:throwingNew

The C++  Standard defines operator new as failing by throwing an exception – not returning null. And indeed, this is the behavior in VC++, and has been for a number of releases.

But it hasn’t always been this way. Back in Visual Studio 6.0, the compiler returned null on an allocation failure. Starting in VS 2002 we switched over to throwing an exception as required, but provided a mechanism (nothrownew.obj) to support the old null-returning behavior.

Why does this matter today? Well, ever since 2002, the compiler has had to guard against the potential of a null returned by operator new. So, in VS 2013 if you write code like this:

 

void foo() {
A* a = new A();
// ...
}

The compiler generates code that conceptually looks like this:

void foo() {
A* a = malloc(sizeof(A));
if (a) {
new(a) A();
}
// ...
}

That is to say, it allocates the memory, checks to see if the return result is null, and if it’s not, runs the constructor on the returned memory.

These null checks are unfortunate: they bloat the code size, they flood the branch predictor, and they inhibit other useful compiler optimizations (like devirtualization, or const propagation out of the initialized object in general). And the compiler has been unnecessarily generating them for the better part of a decade, in a very heroic effort to support people who use nothrownew.obj or write custom non-conforming operator new implementations.

I’m glad to say that in VS 2015 we’re taking the first step towards correcting this: /Zc:throwingNew. When you specify Zc:throwingNew on the command line, it instructs the compiler to assume that the program will eventually be linked with a conforming operator new implementation, and can omit all of these extra null checks from your program.

And here is the best part: when compiling with LTCG, the compiler can detect if you’re using the default (conforming) operator new implementation, and automatically omit these null checks without the need for /Zc:throwingNew!

/Zc:throwingNew may be the default behavior of the compiler in the future, but for now I recommend everyone specify it (especially if you don’t use LTCG) if you’re using the default operator new, or if you only use conforming custom allocators. To add it in Visual Studio, open the Property Pages dialog for your project, select All Configurations from the Configuration drop down, and then open Configuration Properties, C/C++, Command Line. Add /Zc:throwingNew under Additional Options, and click OK.