5 ms·
It's more insane to me that the people who are putting in these "sanity checks" don't know enough about the language to find out that their "sanity checks" are
by kccqzy 2y ago
It's more insane to me that the people who are putting in these "sanity checks" don't know enough about the language to find out that their "sanity checks" are both wrong and useless in the first place.
- tlb 2y agoMany sanity checks are preserved with -O0, so they're still useful in debugging. And they serve as documentation of expected conditions. I often put in checks that I expect to be statically eliminated to remind myself what is supposed to be true.
- shadowgovt 2y agoThe working draft standard for C++ (2022-12-18, document N4928) is 2,110 pages long at a reasonable-sized font. I'd actually go the other way: I think most practicing programmers have not read the entire standard specifying most languages they use day-to-day and have no real idea what the abstraction-break looks like that turns their code into a format consumable by the next layer down. How many Java programmers do we assume know anything about the bytecode of the JVM, for example?
- pjmlp 2y agoWhich includes the whole standard library. The corresponding Java, C#, Python standards, equally with the standard library, are even bigger. To come back to the point, many don't know how deceptively complex Python happens to be, even though on the surface looks like a BASIC replacement.
- int_19h 2y agoTo be fair, even if you look at just the language alone, C++ is still extremely large. But the real problem is when you combine this sheer size with the amount of subtle footguns. If we compare to equivalent Python code, for example, the behavior is simple and straightforward: division by zero causes a runtime error that is reported in a well-defined manner. Similarly with other arithmetic issues in C++ that can trigger UB - e.g. integer overflow is just not a thing in Python (short of OOM). The detailed rules may well be complicated, but it doesn't matter as much when the behavior is intuitive and conforms to common sense expectations.
- kccqzy 2y agoAnd that's why Python is slow and a director at a previous employer initiated a project to rewrite all Python in C++ and the CPU savings far exceeds the cost of some programmers.
- shadowgovt 2y agoIt depends on what you're writing. I've seen slow C++ and fast Python. Not to imply your director made a bad call; especially if you already had a reference Python implementation to check against the new C++ implementation for correctness, you can gain quite a bit depending on The domain you're operating in by swapping out a Python engine with an engine written in another language (if for no other reason and it gives you an opportunity to check all your assumptions against a system solving real problems for real people).
- int_19h 2y agoPython is slow because it is insanely dynamic - much more so than, say, JavaScript. Look into what gets executed for something as simple as a method call before it even gets to the method body. Descriptor protocol etc.
- jimbobthrowawy 2y agoI don't see how it's wrong to use an if statement to check that nobody's passing in a zero to your function that later does division using that variable. c has a whole load of footguns in this area, as UB can impact code appearing earlier in the file. You are right about them being useless or counterproductive in effect sometimes though.
- pif 2y ago> I don't see how it's wrong to use an if statement to check that nobody's passing in a zero to your function that later does division using that variable. Indeed, it isn't. The check becomes useless if it happens after the division, though.
- nemetroid 2y agoOr if the check does not prevent the division (the typical "time-travel" example).
- kccqzy 2y agoDid you notice that the check of divisor being zero happens after the division, not before? It's undefined behavior because the behavior cannot be defined. On Intel you get a #DE before you do the check; this behavior cannot be standardized and that's why it's UB.
- camblomquist 2y agoC++ has an absurd amount of UB to the point where there's an entire thought exercise devoted to how malicious a compliant compiler can be (Hell++.) There are things that are allowed and even common in C but UB in C++ (union type punning,) and things that people reasonably can assume would work but are UB anyway (signed integer overflow.) Then you have weird edge cases like assigning the return value of a two argument std::max involving temporaries to a reference. There are so many UB foot guns, no reasonable developer can be expected to keep track of them all.
- pif 2y ago> things that people reasonably can assume would work but are UB anyway (signed integer overflow.) No, they cannot. You don't have the right to make any assumption about integer overflow in C. Most of the whining about UB is from people who still refuse to accept that you don't have the right to think about your processor family once you write in any language that is not assembly.
- psini 2y agoCannot find any articles discussing Hell++. Is it something specific? The thought seems very interesting and I'd like to read about it if you have any links :-) Thanks!
- camblomquist 2y agoHonestly might just be a Discord in-joke on a C++ server as I can't find much specific either. Sorry for misleading!
- GrantMoyer 2y agoI'm not sure about Hell++, but DeathStation 9000 is a "common" jocular name for a hypothetical system which is as pathological as possible with respect to implementation definined and undefined behavior.
- kccqzy 2y ago> things that people reasonably can assume would work but are UB anyway (signed integer overflow.) Since when is it reasonable to assume that? > Then you have weird edge cases like assigning the return value of a two argument std::max involving temporaries to a reference You have a reference to a temporary. Reference lifetime extension is a thing. No UB there. Completely defined and supported.
- Retr0id 2y agoSanity checks are as much a message to the human reading the code, as they are a message to the compiler/runtime. As a slightly contrived example, assert(sizeof(char) == 1) is true by definition and could be elided, but it might be a useful reminder to see it in the source, next to code that implicitly relies on this truth.
- flohofwoe 2y agoUB is usually not as obvious as a divide-by-zero-constant in plain sight. The divide-by-zero-constant could be the result of a complex constant folding operation, involving values injected into the build process via build options or code generation, similar for any other instance of undefined behaviour. I don't think any programmer puts UB on purpose into the code, even if they can enumerate from memory all 200 or so cases of UB just in the C standard (no idea how big the list is in the C++ standard - thousands maybe?). The original sin was compiler writers exploiting UB for optimisations in bizarre ways instead of working with the C and C++ committees to fix the language to enable those types of optimizations without requiring UB, or at least to classify UB into different 'hazard categories' (most types of UB in the standard are completely irrelevant for code generation and optimization)
- pif 2y ago> I don't think any programmer puts UB on purpose into the code I agree with you. But the problem is not people putting UB in their code, either on purpose or by mistake: we all do that, every day! The problem is people trying to defend their code once it has been made clear to them that it contains UB, and trying to fight the compiler rather than fix their error.
- JonChesterfield 2y agoDo you maintain this stance when the UB is scattered around third party libraries that aren't especially welcoming of patches intended to obfuscate the code while placating some subset of compilers? How about when code is written correctly and then later the standards body makes previously implementation defined behaviour into undefined? I've got some code that calls realloc that WG14 declared to be undefined years after I wrote it and I doubt that experience is unique. The evangelical attitude that the standard committee knows best and your code is wrong and you should immediately down tools to work around the compiler noticing the opportunity to miscompile it is quite popular. I think it's a really compelling argument to build nothing whatsoever on the ISO C/C++ stack and replace what you do have with something less hostile, aka anything whatsoever - rust, python, raw machine code written in hex - none of them have this active hostility towards the dev baked into the language design.
- guenthert 2y agoWhile it is a fair assumption that a programmer using a given language is fluent in it, it's generally unreasonable to expect them to be an expert. Here I bet that not the overwhelming majority of C programmers are aware of the different handling of divisions by zero depending on whether it's a floating point or integer operation. Further, those 'checks' might be in place for a long time, outlasting compiler versions and perhaps even language standards.
- gavinhoward 2y agohttps://gavinhoward.com/2023/08/the-scourge-of-00ub/ https://gavinhoward.com/2023/08/the-scourge-of-00ub/