31 ms·
Falsehoods programmers believe about undefined behavior
- tromp 4y ago> If my program contains UB, and the compiler produced a binary that does X, is that a compiler bug? UB is (usually) input dependent as well. So shouldn't this be phrased as > If the compiler produced a binary that on some input leads to UB and does X, is that a compiler bug?
- eatonphil 4y ago> usually I think this is their point. :)
- vintermann 4y ago> "If my program contains UB, and the compiler produced a binary that does X, is that a compiler bug?" It's not a compiler bug. True, if the language spec is the only thing in the universe you care about. But there are better and worse things compilers can do in the presence of UB, and the big one is warning you about it when it possibly can. There's another big discussion on the front page about signed integer overflow in particular, and gcc screwing the developer over because it was UB when they thought it was just implementation defined: https://news.ycombinator.com/item?id=33770277 https://news.ycombinator.com/item?id=33770277
- rich_sasha 4y agoExactly, some things are probably UB at compile time, these IMHO should by default be a compile time error. Integer overflow is harder ofc.
- morelisp 4y ago> gcc screwing the developer over because it was UB when they thought it was just implementation defined No, the developer thought "UB" produced an integer with an undefined (but still valid integral?) value. They misunderstood what UB is, not whether or not something was UB.
- iforgotpassword 4y agoThat's from the spec POV. On x86 for example, signed int overflow is well defined.
- morelisp 4y agoBoth "UB" and "IB" are terms defined in the language standards, and it's obvious that's what we're talking about here. x86 defines what specific instructions do, nothing so crass as "signed integer overflow" - that's part of why the language standard has to define it as such.
- torstenvl 4y agoYeah, except that they effectively aren't part of the language standard. Possible behavior is to ignore UB, behave in a documented manner, or issue a compiler error. Not remove other code or any other nonsense optimizing compilers do. I'm not gonna wage a holy war against optimizing compilers, but let's not pretend that this is a language standard issue.
- tsimionescu 4y ago> x86 defines what specific instructions do, nothing so crass as "signed integer overflow" I don't understand what you mean. The x86 standard defines what happens if an `add` instruction is performed and the result overflows, possibly affecting the sign bit (what happens is that the OF flag is set, and the target register is set to the two's complement representation of the sum modulo 2^bitlength).
- quietbritishjim 4y agoThat's irrelevant. A C compiler targetting x86 has no obligation at all to handle signed integer overflow in the same way the processor natively does. Because it is not an assembler - it is compiling against the theoretical C virtual machine. This is for the same sort of reason that unsigned overflow does have a well defined meaning in C, and will always do exactly that even for targets that do not natively do that (if necessary it would emulate that behaviour in software).
- Denvercoder9 4y ago> But there are better and worse things compilers can do in the presence of UB, and the big one is warning you about it when it possibly can. The problem is that this is really hard to do without producing either too much or too little warnings, as undefined behaviour is usually input-triggered; and the compiler usually doesn't know all constraints on the arguments that the programmer knows about. For example, the function f() in the article of the other discussion is perfectly well-defined for any argument x <= 0x402010, as in that case no overflow happens. The compiler doesn't know whether all callers ensure the argument is valid (e.g. this might be a library function, or the invariants might not be expressable in a way the compiler can understand). This is a lose-lose situation for the compiler: it can warn, but people will find the unnecessary warnings annoying and turn them off, while if it doesn't warn people will complain about perceivedly bad optimizations. Of course there's a point to be made that the real problem here is that the C standard makes signed integer overflow undefined behaviour, but that's not gcc's fault and can be easily worked around with -fno-strict-overflow or -Wstrict-overflow.
- xg15 4y ago> This is a lose-lose situation for the compiler: it can warn, but people will find the unnecessary warnings annoying and turn them off, while if it doesn't warn people will complain about perceivedly bad optimizations. This could still be greatly alleaviated with the use of asserts: A compiler could default to the most conservative set of assumptions for an input value - e.g. that a parameter of a global function assumes the full value range of its type - unless the programmer provides more assumptions through an assert statement. In debug builds, you could compile those asserts to actual runtime checks, so the program can be appropriately tested. Then, in production builds, the asserts would simply be skipped. The second improvement would be warnings about "nonensical" statements (from the compiler's POV) that will be optimised away. E.g., many of the most egregious examples of UB are from code where the programmer inserted a bounds check to protect against UB at another location - and then the compiler optimized away that same bounds check as a "nasal demon" action, caused by the UB it was supposed to protect against. In those cases, it would be useful to warn "hey, this bounds check can never fail because that other statement implies that either we're in bounds or there is UB. You might want to check for UB here."
- gpderetta 4y ago> there are better and worse things compilers can do in the presence of UB, and the big one is warning you about it when it possibly can. GCC should add -Wundefined-behaviour flag that will unconditionally print "warning: this program might or not have UB" as the first diagnostic.
- jxf 4y ago60% of the time, it's right every time!
- torstenvl 4y agoIt should also warn if there are infinite loops, so the dev can know whether it will ever halt.
- marcosdumay 4y ago"This program may or may not loop forever" Seems pretty viable.
- Kranar 4y agoInfinite loops are undefined behavior in C++.
- deleted 4y ago[deleted]
- Someone 4y agoNo, they aren’t. If they don’t make changes that are observable outside the loop, they can be assumed to terminate. ThTs a compile-time thing. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1509.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1509.pdf (not guaranteed to be equal to the final wording of the standard): “An iteration statement that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.” Rationale for including that: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm (basically, without it compilers can’t optimize loops that terminate as well as with it)
- moring 4y ago> Undefined behavior: Anything is allowed to happen, and you might no longer have a computer left after it all happens. and > The moment your program contains UB, all bets are off. Does this include that a compiler, when it can prove that a program it compiles contains UB, erase your disk as part of the compilation process? i.e. without you ever running the compiled program.
- matkoniecz 4y ago> Does this include that a compiler, when it can prove that a program it compiles contains UB, erase your disk as part of the compilation process? i.e. without you ever running the compiled program. No, but technically compiler would not violate specification by compiling program that on running will scan your disk for secret data, publish it online, apply ransomware to your disk and deliberately destroy your SSD.
- dottedmag 4y agoAlso known as "nasal demons"
- bmacho 4y agoWhat about the C programs? I guess the program void main(){}; is allowed to row hammer your RAM and inspect and modify the states of other programs, but is it allowed e.g. to delete your file system through a system call?
- matkoniecz 4y agoIs it program with UB? If yes, then compiler can compile program doing literally anything* and be in compliance with standards as defined. *including hacking Pentagon to order drone strike on location where it was compiled. Or summoning demons. Or deleting your file system through a system call.
- deleted 4y ago[deleted]
- olliej 4y agoThe biggest problem with UB, as interpreted by C/C++ compilers is the unfounded belief that the spec says that you can assume any path that leads to UB is defacto incorrect and can be ignored. That's the bogus logic required for steps 13-16 to be true. That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work without falling afoul of their invented nonsense.
- maccard 4y agoThis is an absurd reduction of the current situation. > That interpretation of the specification language is clearly bogus as that means more or less all C and C++ programs can be compiled to a single return instruction - when compiler devs introduced this new new interpretation of UB, it turned out they had to then go through and add a bunch of exceptions for basics like memset, memcpy, and memmove could work without falling afoul of their invented nonsense. I've never heard of anything like this, have you any sources for this happening?
- rightbyte 4y agoRead the gcc mailing list. There is alot of user hostile "fix your broken program" from language lawyers. I think aliasing rules messes up memcpy if you are dogmatic?
- ilyt 4y agoTo be fair it is extremely easy to write broken C/C++ program
- maccard 4y agoTheres a big difference between "the GCC mailing list is full of language lawyers" and "memcpy doesn't work because UB and the compiler Devs fixed it by adding an exception for it". > I think aliasing rules messes up memcpy if you are dogmatic? I'm _not_ dogmatic or a language lawyer and aliasing is a total pain in the ass, but that's a whole different topic to compilers getting fundamentals wrong because of language lawyering.
- bjornsing 4y ago> 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. This one came as a surprise to me. Is this really (unconditionally) true? And if so, why? Seems trivial to me to ensure that UB that will never under any circumstance execute will not affect the functioning of an otherwise correct program.
- leni536 4y agoNo, it isn't. The line with UB has to be reached in the execution for the execution to be undefined.
- deleted 4y ago[deleted]
- throwaway294566 4y agoYes, but there is more to it: The compiler may assume that UB will never happen intentionally and optimize out the branch containing UB.
- tsimionescu 4y agoThe compiler isn't required to know if code is unreachable. For example, `if (fermats_last_theorem_is_wrong()) {*p == 1} ` will imply to a modern compiler that p is not NULL in the scope where it is defined, even if we now know that this code will never be reached (assuming that function is correctly written). Or, here is a better example: for(int i=0; i > n;) { } *p=1; Here the compiler will assume that the loop terminates, since non-terminating loops without side-effects are UB in C++. Then, since the loop terminates, p will be dereferenced, so it can be assumed that p is never NULL, so any NULL checks for p in this context can be ellided. This remains valid even if you call this function with an n such that *p=1 is unreachable.
- caf 4y agoIf a some translation unit defines int fermats_last_theorem_is_wrong(void) { return 0; } then a well-defined program can execute that sequence even with p equal to NULL.
- victor82 4y agoIt is not explained why points 31 to 36 are valid, unlike HDL synthesis tools, C compilers are pretty deterministic, same input same output, except timestamps, etc. If an UB adopt X behavior one time, a reproducible build will take same X behavior the next time. Of course I am not negating the fact that this undefined in the first instance nor condoning the UB usage.
- sokoloff 4y agoThat is the observed behavior of the compiler not the defined behavior. (and while there’s some logical reason to assume that will likely continue to hold, the list is falsehoods programmers believe about undefined behavior, not observed behavior.)
- victor82 4y ago"but it worked fine before" talks about the observed behavior
- sokoloff 4y agoYes. That is the sub-category of “among all the falsehoods about UB, these are the falsehoods that can be categorized as [improper reliance on] OB”.
- obi1kenobi 4y ago(Post author here.) Agreed with the parent comment. To restate the same thing in another way in the hope of avoiding confusion: It isn't a bug in the compiler if the compiler is non-deterministic in the presence of UB. Such behavior does not violate any guarantee provided by the compiler or language spec. In fact, it's still not a bug if the compiler is non-deterministic, full stop. Many (most?) compilers have non-deterministic behavior due to a variety of factors. To get a sense of what's involved in getting determinism, look up some articles on why it's difficult to get reproducible builds working. It's a lot harder than it might seem at first.
- 4y ago
- tonetheman 4y agoI am always amazed by articles like these. This guy thoroughly covers this topic. I cannot say I have ever written anything that ran into or caused undefined behavior. And I have programmed for a long time. Is this just an interesting topic or do people actively push the compiler to see what it will do? Maybe I am a boring/simple programmer. :)
- jxf 4y ago> I cannot say I have ever written anything that ran into or caused undefined behavior. But how would you know? :)
- unnah 4y agoThese days it is not quite unknowable, if you always runs your programs with the address sanitizer and UB sanitizer on. They aren't perfect but they would provide a pretty good indicator of whether there was any UB or not.
- sokoloff 4y agoYou’ve never had an integer overflow? You’ve never dereferenced a null pointer? I suspect every C programmer invokes undefined behavior in their first 50 hours of writing C.
- marcosdumay 4y agoIt's quite safe to say that every hand-off between code written by different developers can exercise UB in a few different ways.
- hxhxhrra 4y agoI wouldn't call some cases of UB like overflowing a signed int or running into a dangling reference "actively pushing the compiler". I'm having a hard time believing you didn't ever run into these or similar issues having "programmed for a long time". For other cases (e.g. aliasing, alignment), I'd agree that one is rather safe as long as the dangerous tools (e.g. reinterpret_cast) are not used.
- chrismorgan 4y ago> Here's the list of guarantees compilers make about the outcomes of undefined behavior: > That's the whole list. No, I didn't forget any items. Yes, seriously. I’m a little disappointed there isn’t an empty <ol> or <ul> in the middle there. I imagine screen readers would announce something like “list, zero items”.
- obi1kenobi 4y agoPost author here. I'm very curious about the screen reader idea. If you or someone else is able to confirm what a good screen reader might do currently / what it might do with an empty list element, I'll happily update the post to whatever is the better behavior. I wish there were a best practices doc + a matching linter for accessibility things like this.
- seanwilson 4y agoI just tested "<ol></ol>" in VoiceOver on Mac and nothing gets read. Different screen readers are notoriously inconsistent though. > I wish there were a best practices doc + a matching linter for accessibility things like this. This sounds like it was meant to be a fun tweak/joke for screen readers but it's accessible without. So it's not practical to automate a lot of accessibility checks like this one because it depends on context and there's subjectivity to it, similar to visual design and text readability. The best way to get more of a feel for this is to try a popular screen reader for your OS, do the tutorial, and try it on the page yourself.
- radicalism 4y ago> Different screen readers are notoriously inconsistent though. In other words, UB!
- grogers 4y agoImplementation defined
- leni536 4y ago13. But if the line with UB isn't executed, then the program will work normally as if the UB wasn't there. 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there. 15. If the line with UB is unreachable code, then the program won't crash because of the UB. 16. If the line with UB is unreachable code, then the program will at least stop running somehow and at some point. This is nonsense. The line with UB has to be reached for the execution to be undefined.
- suprjami 4y agoNo it doesn't. Modern processors do out-of-order execution, so your program might be doing UB before you expect.
- cvchjfjb 4y agoNo, no, no. UB is a global property of your program. "All bets are off" even at compile time. "Anything at all can happen; the Standard imposes no requirements. The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended." https://blog.regehr.org/archives/213 https://blog.regehr.org/archives/213
- leni536 4y agoUB is typically a property of the execution of a program. A program may bump into UB for one set of inputs, but not for an other set.
- tsimionescu 4y agoUB is a property of the source code, or more specifically a property of how source code should be compiled into machine code. It means that there is no constraint on the machine code which will be produced if your source code has certain properties.
- cvchjfjb 4y ago
- rurban 4y agoStill no warnings when the compiler does something unexpected on an UB. Major compiler bug in most implementations.
- blub 4y agoAnd if each of those outcomes had a percentage associated with them, I suspect that most undefined behavior would cluster around less than 5 outcomes matching the expectations of even the most junior C programmer. The bunch of amateur bards trying to mythicize undefined behavior really need to find something better to do with their and our time…
- wyldfire 4y agoIt's surprising to see so much debate about when or where UB "happens". Unfortunately this article doesn't refer to the best tool to root out UB - UBSan. If you write C or C++, you should have a UBSan+ASan build that is configured to terminate with an error when it encounters violations. You'll save yourself a lot of hair-pulling later. Then you don't have to wonder about the nebulous topics like what "line" the UB "happened" on. For some compilers, when they add an optimization that capitalizes on an aspect of UB, they will also add a corresponding warning. So make sure you have warnings enabled -- and in most cases you'll want -Werror because generally no one scrutinizes the build output unless there's a failure.
- AstralStorm 4y agoThis is all fine and dandy, but UBSan and ASan are memory hogs that just won't fit in my single digit MB microcontroller. So the only way to run them is too use an emulator, and that means I cannot sanitize drivers.
- wyldfire 4y agoYeah they are and that's too bad. HWASan is another option that reduces the overhead but would only work on a core that had MTE (which your microcontroller is not as likely to have).
- AstralStorm 4y agoActually it is an enhanced armv7 which might work. Though officially HWASan requires armv8. Besides that we have Zephyr stack and heap overflow detection, but it is not quite as accurate as ASan, and does not handle cases UBSan does.
- wyldfire 4y agogwp-asan (like electric fence) is another option for invalid access to heap-allocated buffers. Requires an MMU and creates additional TLB pressure w/some allocation overhead, but no instrumentation overhead and no access overhead.
- Karellen 4y agoIt does seem odd to just "lump unspecified behavior and implementation-defined behavior together" in a side-note under the heading of "implementation-defined behaviour", when that term has a precise technical meaning in the C and C++ specifications.
- csours 4y agoI think that note just means "this post isn't about unspecified or implementation defined behavior". I'm sure you could write articles about each of those.
- obi1kenobi 4y agoPost author here, and yes this ^ is precisely what it's intended to mean. There are also other more exotic flavors of behavior, and the post isn't about those either. I tried to cover as much ground in the post as possible, but the post is already a 10min read and covering unspecified / impl-defined behavior would have made it a 20min read instead :)
- Karellen 4y agoI did get that eventually, but I missed the side-note in my first read through, and it was lumping two concepts together under the name of one of them that I found confusing. If, in your description of the three buckets, you called the middle one something else like "Platform-dependent behaviour" or whatever, I think that would have been less weird. You'd still only need one short paragraph to say it's compiler/OS/hardware dependent, covers implementation-defined and unspecified, and is not the focus of the article.
- machrider 4y agoI guess the thing about dragons was true; it's not mentioned in this list.
- hoosieree 4y agoUB is not allowed in a constant expression in c++, which is a good reason to put constexpr in front of as many things as you can.
- gpderetta 4y agoYou need to actually invoke at compile time your constexpr function with the specific arguments that would cause UB to actually get an error. It is not significantly better than running your test cases with with UBsan but it is a nice feature.
- hoosieree 4y agoGood point. Also UBsan and Asan are great additions to any C/C++ workflow. But if it's actually part of the code, I'm forced to use it even if I'm lazy, versus an external tool that I can forget to run (or forget to add to my build system). Leveraging what the compiler gives you is like that saying "the best camera is the one you have on you".
- gpderetta 4y agoGood point. I love constexpr because it allows me to write compile time unit tests inline with the library code, with static_assert. The implied UB check is gravy.
- leni536 4y agoWhile theoretically true, there are a whole bunch of undefined behaviors that are not caught in constexpr context in practice. In particular unsequenced operations on the same object are typically not caught. It's still super useful though, and more common language UBs are caught.
- hoosieree 4y agoThat's a compiler bug though, right? Doesn't the standard disallow UB in constexpr?
- mnw21cam 4y agoI have a suggestion - it may be completely off the wall, but hear me out. C needs a mechanism to declare in a source file that certain behaviour must be defined, where that behaviour is undefined in the C standard but the target architecture behaves the defined way. Then, when the source is compiled on the target architecture it works as expected, but when compiled on something else it refuses to compile. For example, unsigned ints. It'd be great to be able to declare "I define int to be 32 bits and to overflow like a sensible 32-bit int - treat this as defined behaviour, and refuse to compile on a system where this isn't true." The number of platforms where this would fail to compile would be extremely small, and at least they would give a sensible compile error on systems that are weird.
- yladiz 4y agoI have almost no idea about C compilation but would it be possible with macros or somehow redefining int?
- mnw21cam 4y agoI don't think it'd be possible to get the compiler to treat unsigned integer overflow as defined using macros. But I'm not a subject matter expert.
- variadix 4y agoNot cleanly, but if you assume 2s complement and wrap all signed addition in a macro function you could cast to unsigned before the add and cast the result back to signed.
- obi1kenobi 4y agoSuggestions like this are unfortunately quite infeasible (they fall under the hat of "define all the behaviors"), and the talk I linked in the post goes into why: https://www.youtube.com/watch?v=yG1OZ69H_-o https://www.youtube.com/watch?v=yG1OZ69H_-o (I'm the post's author.)
- 4y ago
- nmilo 4y agoI thought this was going to be an actually useful post about the details of UB, when it happens, and what it generally looks like, but instead it's just more of the same often repeated "if you write a program with UB your compiler will literally summon dragons and wipe your hard drive and kill you in your sleep." The truth is that practice diverges from theory, and, in practice, it is actually useful to talk about UB as a thing that happens and not as some mystical aura the compiler can sense or not. Leading to, in practice, almost all of these points being, if not flat-out wrong, at least unhelpful or misleading to the average programmer. For example: > 14. Okay, but if the line with UB is unreachable (dead) code, then it's as if the UB wasn't there.[1] The linked post ([1]) doesn't even showcase this phenomenon, it shows something completely different, where ignoring a 3 transmuted into a bool causes more UB. The problem was that you already had UB to begin with when transmuting a 3 into a bool. I want to see a godbolt output where the claimed: if (false) { run_ub(); } actually causes problems. > 28. At least it won't completely wipe the drive.[2] This is just unhelpful for anyone trying to learn more about UB. UB can call parts of your code that would otherwise be dead, which is a useful piece of information to know. And if you literally write "rm -rf /" in these dead sections, then yeah, I guess UB is technically wiping your drive, but stating it like that just gets in the way of anyone trying to learn more about UB and just perpetrates this unhelpful theory that UB can literally do anything it wants, such as... > 30. At least it won't start playing Doom if the program didn't already have the Doom source code in it. Really? > 31-32. If a UB-containing program "worked fine" previously, recompiling the program without any code changes will still produce a binary that "works fine." Recompiling without code changes and with the same compiler and flags will produce a binary that still "works fine." Recompiling as above + on the same machine will produce a binary that still "works fine." In practice, compilers are generally deterministic. I see no reason this should be the case. Don't link me a sadistic compiler that randomizes code output. Finally, > The moment your program contains UB, all bets are off. is blatantly untrue. All guarantees are off, but I can bet what most programs with UB do, and it is still useful to be able to reason about what programs with UB do. For example, I can tell you what: int main(int argc, char \*argv) { int *p = NULL; *p = 4; } does on O0 on my machine, and most linux machines, despite the fact that it is untrue for "Any kind of reasonable or unreasonable behavior happening with any consistency or any guarantee of any sort." You guys are engineers right? Software engineers? Why don't you do what all engineers are supposed to do and that is use experience and intuition to know when theory applies in practice, and when it doesn't? [1]: https://www.ralfj.de/blog/2020/07/15/unused-data.html https://www.ralfj.de/blog/2020/07/15/unused-data.html [2]: https://kristerw.blogspot.com/2017/09/why-undefined-behavior-may-call-never.html https://kristerw.blogspot.com/2017/09/why-undefined-behavior...
- singularity2001 4y ago… "what the compiler guarantees in the presence of UB" What? Undefined behavior means the compiler guarantees nothing, per definition.
- slicktux 4y agoDivide by zero was one that I always believed would give segmentation fault…but that is totally not the case; I’ve gotten Infinity as a return once… I forget what compiler gives what…
- johnhenry 4y agoJavascript?
- slicktux 4y agoAh, I did not specify; with GCC… I believe it was compiling as C vs C++
- tristan957 4y agoMy experience is that you get SIGFPE for division by zero errors.
- koala_man 4y agoMy least favorite thing about "falsehoods X believe about Y" articles is that they make a point out of not backing up or demonstrating any of their claims.
- obi1kenobi 4y agoFortunately, this post includes a link to an excellent 45min talk on undefined behavior which does go into a fair bit of the detail you were looking for. I encourage you to click it -- it's right in the post's introduction. The purpose of this post and other "falsehoods" posts is to shine a light on the existence of a misconception or set of misconceptions. By that point, there are usually plenty of other high-quality posts about "why / how / when" etc. but for a variety of social dynamics reasons those posts by themselves did not have the wide distribution and readership they deserved. After shining a light on the misconception, interested readers are generally able to continue the learning process both through the sparked discussion and through doing their own searching. Here's a specific example of such a post with even more details: https://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html https://blog.llvm.org/2011/05/what-every-c-programmer-should...
- scoutt 4y agoI have another falsehood: most programmers believe that people working with C/C++ are constantly battling against UB all day long, five days a week, and that they are irresponsable and careless. That they should live in fear and terror, because "unsafe" is around the corner, and that their programs are not mathematically proven and that they might containt an explotaible bug because, you know, every other C/C++ program opens a socket to the internet or is a "sudo" kind of tool.
- mattarm 4y agoAn automobile recall is a good analogy here. Most people driving cars with an active recall are unaffected by the problem the recall is supposed to address. They can drive on blissfully unaware that something could go wrong. They might even enthusiastically recommend that others purchase the car they drive. For a few people, they'll experience a failure, possibly a dangerous one. And this is the root of the problem. The fundamental concept of using a language prone to UB exposes all programs to a small risk. In isolation, the risk is small. In aggregate, the problem is real.
- scoutt 4y agoThe same applies to vaccines and medicine drugs. Should we stop giving them to people? "For a few people, they'll experience a failure, possibly a dangerous one.". Should we try our best to minimize the risks? Absolutely. But we are talking programs here. We shouldn't measure every program with the same ruler. Not all programs need to be MISRA compliant when they don't need to. My Reddit app crashes several times a day, and I guess there is no immediate danger.
- Quekid5 4y agoThere are no viable alternatives to vaccines and medicine in general (ones that actually work, that is). There are alternatives to C -- for most cases. > My Reddit app crashes several times a day, and I guess there is no immediate danger. That's because your app is heavily sandboxed and probably (on Android, at least) running in a VM which enforces memory safety and isolation from other apps. If each crash had, say, a 1% likelihood of eating a large portion of your data (or leaking pictures or whatever) you'd probably care a lot more about it. The problem highlighted by the parent poster is that all these little risks add up and often end up being catastrophic (e.g. heartbleed) because so much of what we run is interconnected via the network (or just data in files).
- layer8 4y agoThe way to think about UB is that it’s like a false premise. Anything and everything can be derived from a false premise. Compilers can end up with arbitrarily false conclusions if the program contains a false premise. The other important thing to realize is that UB is generally a runtime condition and cannot be detected statically, in the general case. That’s usually why it’s been made UB in the first place.
- quelsolaar 4y agoThis post is very good. One thing to add, is that if you code has not entered a state of UB yet, but will at some point, then all bets are off. The phenomenon is generally known as time traveling UB. Compilers assume your code doesnt contain UB. Example: If(x == 0) printf(“hello”); y /= x; The compiler can assume x is not zero because it assumes the user will not cause UB, therfore the if statement and printf can be removed.
- bhk 4y agoAnother falsehood programmers believe about UB: - Compilers and language designs could not improve on this situation without sacrificing performance or portability.
- VMtest 4y agosecurity, it's important
- bigbillheck 4y agoI'm halfway through watching that Chandler Carruth video the article linked to, and I feel like I'm getting lectured at. It's making me not want to ever write c++ ever again (Unfortunately I'll have to be writing c++ for a while longer)