clang test.c -O0 -fsanitize=undefined
./a.out
[...]
test.c:17:12: runtime error: 9.22337e+18 is outside the range of representable values of type 'long'
Interestingly gcc doesn't throw that warning.
clang test.c -O0 -fsanitize=undefined
./a.out
[...]
test.c:17:12: runtime error: 9.22337e+18 is outside the range of representable values of type 'long'
Interestingly gcc doesn't throw that warning.
There also exists low-cost random-sampling-based ASAN implementation that can be enabled in production: Google uses GWP-ASAN for all server-side applications as well as Chrome on Windows/Mac. See https://www.youtube.com/watch?v=RQGWMLkwrKc for details.
Here 14%, https://www.jetbrains.com/lp/devecosystem-2019/cpp/
Here 40 - 55%, https://www.bfilipek.com/2019/12/cpp-status-2019.html
At CppCon 2015 or something, at Herb's question during his keynote, about 1% of the audience as per his comment on the video.
The reason they aren't enabled by default is that that's not what they're designed for. They have a significant performance impact, you can't enable them all at once, they conflict with other security features and they may introduce security issues.
These are developer features. They aren't there to run your production code, they are there to test during development and bug finding.
$ g++ -x c++ -fsanitize=undefined -
#include <iostream>
int main() {
int *a = nullptr;
std::cout << std::addressof(*a) << std::endl;
}
^D
$ ./a.out
<stdin>:5:29: runtime error: reference binding to null pointer of type 'int'
0Can you cite me something for that? The very first mention of dereferencing in the C++03 standard - ISO/IEC 14882:2003 1.9 Program exection ¶ 4 (page 5) - would seem to disagree:
> Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer). [Note: this International Standard imposes no requirements on the behavior of programs that contain undefined behavior. ]
EDIT: As does 8.3.2 References ¶ 4 (page 136):
> [...] [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bit-field. ]
> Notes from the October 2003 meeting:
> ...
> We agreed that the approach in the standard seems okay: p = 0; *p; is not inherently an error. An lvalue-to-rvalue conversion would give it undefined behavior.
http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#232
WRT your edit: no, that says dereferencing a null pointer and binding a reference to the result produces undefined behaviour. That agrees with what I was saying. "which" refers to the whole of "to bind it to the "object" obtained by dereferencing a null pointer", not just to "dereferencing a null pointer".
> neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue
sizeof on invalid pointer dereferences is also pretty common.
This sounds like a good UB learning experience. The parent comments sounds like the author is running into UB more than they really want to.
On the other hand, the clang static analyzer may have a shocking amount of messages when run first on a large existing code base, and some of those warnings can be considered more "opinions" than warnings. It's still makes sense and is very rewarding to make a code base "static analyzer clean".
The runtime sanitizers in comparison are very precise and always pointed to actual "sleeper bugs", it's almost definitely a good idea to use them and take their warnings serious.
But anyway, clang ASAN, UBSAN, TSAN and the static analyzer are all really excellent and important tools for everybody writing C or C++ code.
PS: the reason why those checks are optional is that they increase compilation time (sometimes dramatically, like 10x slower compilation or more), and they add runtime instrumentation code which both increases the executables size and decreases performance dramatically (also 2..10x times or more, although the clang sanitizers are really quite fast compared to other solutions).
The best projects are the ones that start out from day 1 with all the pedantic warnings turned on, warnings-as-errors, static analysis and sanitizers run as part of the automated build and any peep out of them gets treated just like an error would get treated. When you start the project out that way, there isn't that de-motivating initial hump to get over.
Current codebase generates around 3000 casting errors. I doubt I'm the only one with this kind of "history" to deal with AND the application is crashing with memory access errors.
What's my cleanup plan for this? Multiple compilers with every warning enabled on multiple platforms. Even a platform we're not targeting. We've mapped out which files and which lines have the biggest code smell. Now we have a giant map on a 65" tv to guide us.
Why all this attention? We're moving this nightmare from 32 to 64 bits. Parts of it were originally 16bit which have already been updated. Cast errors alone are now signposts to other bad code.
It helps that you then almost certainly have buy-in and are allowed to treat this as a priority because it's tied to work that the business is willing to prioritize. You're already over the hurdle of "customers don't pay to fix compiler warnings".
Getting rid of the warnings and more importantly the related other debris means being able to use enhancements we make each week. Well... after qa/test have done their thing.
Been good practice for my own indie dev. Treat every warning as an error and make a habit of running a detailed reporting build each day or week. The trick of using other platforms and compilers I brought from years back.
(TIL - thanks!)
Note that ruining sanitizers in prod might be insecure. They're for development.
It's pretty much established that even expert C and C++ programmers, especially for larger code bases, will end up making some sort of mistake that will cause a security vulnerability or undefined behavior.
I used Delphi on Windows. Most of the code I wrote in the last 20 years is in Pascal.
And that works really well on Windows. You have a stable API, and it does not matter what language the API is written in. Any language can use the API in the same way.
I tried to run some old projects this month. My 20 year old Delphi Windows programs run better in WINE on Linux than most programs I wrote 5 years using Linux tools, because the libraries have changed, but the API has not
ripgrep cannot be a drop-in replacement. Despite that, it can certainly replace grep in a wide variety of use cases. See: https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#pos...
* Probably because the Ada practitioners are all trapped in Scifs somewhere in the inner mantle of the Earth.
20 years ago it was advertised as the safe C alternative.