24 ms·
This has nothing to do with K&R or whatever new C standard there is. You're talking trash. The rules around UB can be annoying, but I don't think this is a rec
by jstimpfle 5y ago
This has nothing to do with K&R or whatever new C standard there is. You're talking trash.
The rules around UB can be annoying, but I don't think this is a recent development, either. Probably compiler optimizations are to blame for some of this. For actual practice and pedestrian code, obscure UB bugs have little relevance.
Food for thought: C compilers are free to insert runtime checks to abort when UB occurs.
- vlovich123 5y agoUB was standardized in C99 and optimizers started really going after it maybe 5-10 years after that. There was a wide spread push to make the issue more widely known 8 years ago-ish if I recall correctly and most people still don’t fully understand it. I wouldn’t say it’s “new information”, but it’s certainly relatively new in the overall lifetime of the language (ie even a lot of C99 code from that era is malformed on today’s compilers). I understand the basic concept of UB but some of the rules can have nuance and be easy to run afoul of. If you’re not running UBSAN on non-trivial codebases (lots of LOC and/or multiple devs), you are likely to have UB. Same goes for ASAN and TSAN issues. I always have humility around this topic as I’m not a compiler author. Heck, the compiler authors I’ve worked with themselves know the knives are sharp and work with humility.
- jstimpfle 5y agoTotally agree with your post. I don't know what your conclusion is, though. My conclusion is that C lets me do what I want straightforwardly, I still haven't found this quality in a different language (there is inertia, I've only tried Zig for an hour for example and gave up in frustration). Also, to some degree I understand where most UB definitions are coming from and even agree with some of them. The basic idea behind UB is to give the compiler a free pass (optimization, and not having to detect corruption) if the program has a bug anyway. In some cases there can be legitimate surprises, when the programmer made some assumptions about guarantees that C can't give and that a newer language (without the historical baggage of supporting some architecture) can give, which might result in the compiler transforming a little bug into something bigger (more dangerous?). An example that I've personally learned at some point is integer shifting and masking in conjunction with implicit type promotion to int (which is signed). All in all though, while I'm not be the most sophisticated programmer and most of my programms are never exposed to hacking attempts, just anecdotally I've had very, very little headaches from UB.
- vlovich123 5y ago> My conclusion is that C lets me do what I want straightforwardly, I still haven't found this quality in a different language C is the language where you've found things to be straightfoward? I'm curious what you're working on where this is the case. I'd reach for Python, Go, Java, Swift, C#, depending on what I'm trying to do (even C++ can be better, but it comes with its own unique additional set of footguns so some C acolytes tend to shy away from it). For most projects (at least those starting from scratch today) I'd probably choose Rust if C/C++ would otherwise be the only appropriate choice & use Python/Go/Swift/Java/C# elsewhere. > All in all though, while I'm not be the most sophisticated programmer and most of my programms are never exposed to hacking attempts, just anecdotally I've had very, very little headaches from UB. and > An example that I've personally learned at some point is integer shifting and masking in conjunction with implicit type promotion to int (which is signed). Is an interesting mix of statements. I can say that I've worked on quite a few large codebases with a myriad of contributors, & I've always uncovered UB when I went looking for it. Some of it harmless, others less so. It's a "this probably is invisible 90% of the time you run it locally" kind of thing, so unless you have thorough tests you can run under UBSAN, you're likely just unaware of the scope of the problem. That being said, I don't want to blow it out of proportion. I'd say memory safety & thread safety are bigger classes of issues. As with UB, if you're not running sanitizers with very large test suites, you're unlikely to see it [1][2]. As for why UB is a real problem conceptually, this used to be well-formed and correctly behaving pre-C99: ``` uint8_t x = <pointer to some buffer> uint64_t y = (uint64_t)x; ``` I don't mean in a "this just happened to work" but in a "this was valid semantics of the language". Now it requires a memcpy. It's also entirely possible this is valid in C & not C++? That's what I mean by UB being very subtle. Yes, I understand why UB is important to allow compilers to generate more optimal code. I think Rust strikes a better balance here - most code doesn't* need that tradeoff and where it's important can be explicitly annotated with that fact. Ultimately, to me the fact that even the Linux kernel is subject to these kinds of issues[3], gives me enough pause to believe it's a real problem in the ecosystem (among many others). So other, safer languages, are usually better if you can use them. Most experienced developers should have a number of languages under their belts they're fluent in and be able to switch to languages they haven't seen before (albeit there's always a cost & it's not fun, so I don't seek it out as often as I maybe should). [1] https://reviews.llvm.org/D51170 https://reviews.llvm.org/D51170 [2] https://bugs.llvm.org/show_bug.cgi?id=23293 https://bugs.llvm.org/show_bug.cgi?id=23293 [3] https://software.intel.com/content/www/us/en/develop/blogs/null-pointer-dereferencing-causes-undefined-behavior.html https://software.intel.com/content/www/us/en/develop/blogs/n...
- pjmlp 5y agoTrying to attack me won't do a thing, remember comp.lang.c? Plenty of Usenet experience over here. If you don't like it to be pointed out C's weaknesses, don't engage. I can play language lawyer quite well, including security standards. Yes compilers are free to do many things to fix C, except that many don't.
- jstimpfle 5y ago> Yes compilers are free to do many things to fix C, except that many don't. But this is the point. The language is quite compact and simple and if you think like a computer, it just "makes sense". Counting pages of the standards is not an accurate measure of language complexity. Certain subtleties are not even forced by the language, rather they arise from real world requirements (such as performance, implementation simplicity, modularity, compatibility, etc). By and large, it's not the language, but rather what people do with it. The language gets out of the way.