Undefined behavior can result in time travel (2014)
devblogs.microsoft.com
devblogs.microsoft.com
So that's how it was, and the code base was littered with lots of little checks on what new expressions were returning, things like:
int *p = new int[1024];
if (!p) return SOME_ERROR;
doSomething(*p);
Of course, the C++ standard says that operator new will never return null (it's supposed to throw if it fails). So the compiler sees this code and says "hey, that if (!p) check isn't necessary.." and so none of those little checks gets emitted. Sure enough, it happens that the operator new returns null now and then because everyone is on a tight memory budget, but instead of catching it and returning an error, the code just goes on to crash. int *p = new (std::nothrow) int[5]; // gives null if alloc fails
A related question: Many C++ coding standards, including Google's, prohibit use of C++ exceptions. Do they have to use the nothrow syntax everywhere the new operator is used?[0] https://www.cplusplus.com/reference/new/operator%20new[]/
As the post says, malloc can return null even where overcommit is used; it's not true that malloc never fails when overcommit is enabled.
Even if it were true that malloc/calloc/realloc/new/new[] could never fail on your OS+compiler, it doesn't seem wise to write code that relies on that non-standard guarantee. Poor robustness and portability.
However, the big companies like Apple, Facebook, and Google simply don’t care about standards compliance in their internal C++ code bases. At least, not as an end goal. There are a lot of good talks about this.
If you fail to allocate memory, there’s a good chance that your process can’t continue servicing requests anyway. So, it’s a good tradeoff to abort. The client can retry later or with a different backend, and the job scheduler can start another instance of the process.
By the author's logic, even if the undefined behavior didn't exist, you can still assume i is never 4 or 5, but that doesn't meant the function always returns true. Is there something I'm not understanding here?
if (table[i] == v) return true;
line has an implicit `else continue;` clause, not an `else return false;` clause.That makes sense, but still feels like a broken way to do optimizations.
runtime error: index 4 out of bounds for type 'int [4]'
UndefinedBehaviorSanitizer: SEGV on unknown addres
runtime error: reference binding to null pointer of type 'int'
Not if the compiler got to it first. If the compiler does what Chen points out it can do, you won't be indexing anything at run time.