8 ms·
> C++ compiler generates the code the programmer asked it to generate Many C++ programmers would be much happier if this was true. Undefined behavior ends up t
by overgard 5y ago
> C++ compiler generates the code the programmer asked it to generate
Many C++ programmers would be much happier if this was true. Undefined behavior ends up turning this into "C++ compiler generates the most efficient thing that may or may not correlate with what you intended"
- tialaramex 5y agoBut that is what you asked it to generate. The gaping chasm between what a C++ programmer intended and what they managed to express by writing C++ is where many (not all, but many) of the problems slip in. I contend that the most important goal of a programming language is that the author, the compiler and any subsequent maintenance programmers all agree what has been expressed. To the extent that your language fails in this (and I argue C++ fails badly and almost constantly) it is a bad programming language. The existence (albeit not so common in practice with good tooling) of invalid C++ programs which nevertheless compile is a particularly terrible indictment of the language. In this case the author, and likely maintenance programmers (at least until the compiler gets updated to detect their particular case) believe they have written a C++ program, but the compiler silently does not agree and the results might be anything whatsoever.
- titzer 5y agoIt is worth noting that C/C++ are essentially the only holdouts that disagree with your (quite reasonable) conception of a programming language. C/C++ treat programs as vague suggestions of machine code, and the vast intricacy of their compiler optimization pipelines give not one single f*ck about screwing up a program that has UB. This entire ecosystem is littered with user-hostile anti-patterns that put the onus on poor programmers who have had the audacity to...not initialize a variable properly, or overflow an integer.
- dizzant 5y agoComments like this are a dime a dozen on HN. Every time I see one, I wonder what horror raises such ire. I like C++ and use it voluntarily for my research. How did it bite you?
- titzer 5y agoI've been programming in C++, sometimes heavily, since 1998. I worked on V8 for almost 7 years. Those were some of my worst debugging experiences (truth be told, usually at the mercy of my own mistakes in the JIT there.). They say that you can shoot yourself in the foot in C, and blow your leg off in C++. And that's because UB can mean the compiler's dirty tricks all become part of the mystery as to why exactly a program crashed the way it did. I used to ask as an interview question, "You have a C program that crashes. You add a printf and it stops crashing. Why?" There is no right answer...the list is a mile long of things that could be wrong. Obviously it's a bug in my program, in my code. But damned if every tool in the whole chain is going to be so damn unhelpful in finding it. They tell me it's my fault but they proceed to puke their internals at me and let me try to figure it out! Ugggggh!!!! So I screw up my program, but BAM! Suddenly I am thrust into a complete alternative reality of machine implementation details, a metric asston of low-level irrelevant information...and somewhere in there are clues only I can work out. It was the optimizer! Because my program triggered UB, some insanely complex chain of compiler reasoning led it to the mess that is there now. I am forced to debug the actual machine code. I must. Or its tendrils, raw addresses spewed by a debugger, trying to picture in my head how the fuck these two datastructures got overlapped in memory wrong but it only shows up in optimized code, but manifests in a super-misleading crash. And it was because a field was uninitialized and for some other damn reason it was just working before, like the memory was already zero'd by accident, because it was reusing some specific pattern of deallocated memory, meaning that something was just kinda magically perched on top of it, hiding that bug....You realize it's a very fragile stack of stones. And then you realize the whole tower is at risk. The code actually has bugs. Right now. Bugs you haven't found yet. Bugs your idiot savant super-intelligent mega-optimizing compiler is recruiting the sum total of hundreds or perhaps thousands of smart humans who think of new ways to make the code go faster, but never bother to reason about undefined behavior, leaving it entirely questionable as to future results of the program you have written today, or happen to be ever-so-unhappily in charge of, but...but...is full of bugs. UB bugs. Like, the worst kind. In the limit, you must fear that a completely super-intelligent compiler would at this point conclude that all C/C++ code having bugs is wrong and will technically replace it with a no-op. Suddenly computers stop booting after a software update because the AI optimized away the kernel to essentially the minimal thing that can pass the compiler's unit test suite, but otherwise is a no-op, mass hysteria, cats and dogs living together. Ok, maybe I made that last part up. But yeah, this UB thing is really bad. I feel like I am taking crazy pills, because to me the experience of working with C++ is like being a grunt stuck on a 2 mile-long digging machine that has all the controls set to "BECAUSE FAST" and the only answer to "why all this?" is the computer-programming-equivalent of a kick in the nuts. I seriously hate that experience. I mean seriously, as a compiler person, I love looking at machine code. But that's no way to debug programs. It sucks. Arguably the absolute first job of a programming language is to try to raise the abstraction level. But we can't. Because this stupid language pukes the machine at us. We are fundamentally incapable of raising the abstraction level with C/C++ and drown in a just total cesspool of wasted human effort.
- passivate 5y ago>I contend that the most important goal of a programming language is that the author, the compiler and any subsequent maintenance programmers all agree what has been expressed. To the extent that your language fails in this (and I argue C++ fails badly and almost constantly) it is a bad programming language. I'd disagree, but only slightly. I think the most important aspect of any programming language is the ecosystem. By that I mean ready access to high quality training material for novices, large community of developers willing to help and mentor, and a healthy ecosystem of tooling, libraries and other infrastructure. I think with a lot that has changed in C++, the language, the 'high quality training material for novices' hasn't kept up. I don't think the language is that appealing to novice programmers anymore. I also don't think its a 'bad' language, but I may agree that its past its prime.
- pjmlp 5y agoA practice started with C, which C++ had to keep compatible with, given its origin as a C preprocessor. C's authors were already aware of this issue, hence why in UNIX fashion they outsourced the validation to yet another tool, lint. Unfortunely to most of us, users of software written in such languages, static analysis keeps being ignored by the large majority (about 11% usage per usual language surveys).
- jstimpfle 5y agoIt's not that the compiler does not agree. It's that it operates under the assumption that there is no UB. If the compiler knew for sure that there is going to be UB (which happens at runtime, not compile time) of course it would tell. (Surely in some cases, the compiler needs to be improved to see UB that can be detected statically without much effort). And if you don't request heavy optimization, what happens when UB occurs is likely just what you expected to happen on that particular machine. If you do request optimization, the results might be more off (perhaps the compiler removes some codepath for example). But I always have the impression that UB horror stories are mainly that: stories. I'm only slightly ashamed that I can't tell one from my personal experiences.
- passivate 5y ago>Undefined behavior ends up turning this into "C++ compiler generates the most efficient thing that may or may not correlate with what you intended" What normal C++ syntax are you referring to that generates undefined behavior?
- jzwinck 5y agoFor example, incrementing an int until it overflows.
- passivate 5y agoMy point was what are examples of normal C++ code where the language obviously deviates from the intention of the programmer and screws them over with undefined behavior. I don't see how any programmer can "intend" to use a data-type assuming an infinite range - or assuming specific wrapping behavior that was never guaranteed to them by the language. If a programmer is unaware that language data types have finite ranges and/or specific wrapping behavior then that is a problem that can be easily solved with training.
- ModernMech 5y ago> If a programmer is unaware that language data types have finite ranges and/or specific wrapping behavior then that is a problem that can be easily solved with training. The thing is that everyone recognizes this and yet entire categories of bugs that are easily caught with appropriate language design and tooling nonetheless persist in C and C++. Yes, a programmer who does not understand the footguns involved with e.g. integer overflows can be trained to understand them and avoid them. But for every one you train, there will always be another novice programming ready and willing to use the footguns. And even if you do train every last one and every new one, they still have to practice discipline and be vigilant forever more to avoid these problems. Discipline doesn't scale. It's far better to enforce good behavior at the language level, rather than expecting you'll be able to train your way around these issues.
- 5y ago