4 ms·
You can at run time with ubsan. At compile time it doesn't make sense, because undefined behavior is used for cases where the overwhelmingly common case you won
by bonzini 8y ago
You can at run time with ubsan. At compile time it doesn't make sense, because undefined behavior is used for cases where the overwhelmingly common case you won't see undefined behavior. It'd have 99% false positives, pretty much by definition.
- inetknght 8y agoDevelopers who have to work with actual responsibilities need to take those edge cases "you won't see" into account.
- platinumrad 8y agoCorrect me if I'm wrong, but I think you're misunderstanding what they're saying. They're not saying that undefined behavior can be ignored because it "probably won't happen" or something like that. They're saying that undefined behavior is everywhere in the C standard and that this fact is commonly exploited for the purposes of optimization. For example, signed integer overflow is undefined behavior which allows the compiler to avoid extra sign extensions when indexing in a loop. Would you want a warning to be emitted at compile time every single time you write "for (int i = 0...)"? I'm sure that would actually end up doing more harm than good as it would just condition people to ignore these warnings altogether. As the poster mentioned, ubsan will catch the cases you actually care about, albeit at runtime. It's also worth noting that GCC does try to warn at compile time about a lot of the undefined behavior that you do care about, such as strict aliasing violations when -Wall is enabled.
- 0db532a0 8y agoCould you explain why in this hypothetical scenario a warning should be emitted for “for (int i = 0...)”?
- inetknght 8y agoRange-based for loops are far more idiomatic for modern C++: https://stackoverflow.com/a/15089298/1111557 https://stackoverflow.com/a/15089298/1111557
- saagarjha 8y agoThey're also not in the standard library. Not everyone can justify integrating Boost into their applications :(
- Y_Y 8y agoYou can certainly do this with just the standard library and no boost, for example using iota from <numeric>. https://en.cppreference.com/w/cpp/algorithm/iota https://en.cppreference.com/w/cpp/algorithm/iota
- saagarjha 8y agoThat’s not a generator, though. You need to allocate an extra container for this to fill, which is inconvenient.
- bonzini 8y agoAnd underneath they compile to an int for loop and a pointer dereference, both of which can be undefined behavior.
- platinumrad 8y agobonzini's hypothetical scenario was one where the compiler emitted a warning every single time it encountered undefined behavior. Assuming that a loop counter cannot overflow because signed integer overflow is undefined is one such instance and would fall under the "99% false positives" that they mention.
- inetknght 8y ago> Would you want a warning to be emitted at compile time every single time you write "for (int i = 0...)"? Yes, I would. I have transitioned to always using ranged loops. I haven't had to write a "for (int i = 0...)" style loop for over a year. Even one where I thought it was still needed, I learned about zip iterator adapters from a C++ conference video; wrote my own, paired it with a proxy iterator, and the problem solved. Everywhere such a loop has existed, it has been replaced with generator class to provide the range needed. Not only would I want a warning, but I'd personally turn the warning into an error. I'm one of those dudes who runs around with pretty much as many warnings as possible turned on, and most of them turned into errors. Most of the warnings that are disabled by default are extremely helpful in preventing simple errors. Understanding what those warnings mean and how to resolve them is something I consider to be core understanding for anyone who wants to become more than a junior C++ developer. There's a _ton_ of libraries that don't work like that. Sucks to be them. Linking to boost works (most of the time) though, and that's the only real hard requirement I have.
- platinumrad 8y ago> I'm one of those dudes who runs around with pretty much as many warnings as possible turned on, and most of them turned into errors. Most of the warnings that are disabled by default are extremely helpful in preventing simple errors. Understanding what those warnings mean and how to resolve them is something I consider to be core understanding for anyone who wants to become more than a junior C++ developer. I strongly agree, which is why I think it's important that these warnings are not spurious. -Werror is no longer viable if what it takes to resolve warnings is more ceremony than substance. Emitting a warning every single time the compiler encounters undefined behavior would be utterly overwhelming given that the vast majority of these instances are harmless like skipping a load because it would be undefined behavior for a couple of pointers to alias. Obviously GCC and Clang could do more (for example, Clang doesn't implement -Wstrict-aliasing if I recall correctly), but their current approach of warning about UB when harmful, rather than reporting all UB, is correct in my opinion.
- bollu 8y agoThis is not going to save you either. To have this be efficient, the compiler needs to prove many things: for example, that the end iterator and the current iterator come from the same base object. Compilers don't do this, because comparing iterators from two different objects is UB.
- cryptonector 8y agoYes, I do. It's easy to get into a habit of writing "for (size_t i = 0; ...)".
- cryptonector 8y agoThis is nonsense. The optimizer makes decisions based on UB at compile-time. It should warn about this, especially when deleting code. > overwhelmingly common case you won't see undefined behavior. You think so. But this actually can be a source of serious security vulnerabilities. I want at least the option to know.
- bonzini 8y agoWould you like to have a warning for every "for(i=a; i<=b; i++)" loop, where the compiler assumes the loop is not infinite? Or for every a[i++] in a loop (including a[i] with i++ in the for loop of course), where the compiler assumes it can convert the induction variable to *p++? Both of these are undefined behavior if "i" is signed and it overflows.