6 ms·
Because a lot of UB cannot be efficiently determined at compile time. Hence, UBSan.
by dom0 9y ago
Because a lot of UB cannot be efficiently determined at compile time. Hence, UBSan.
- pjmlp 9y agoIt is very easy to be efficiently determined at compile time, other systems programming languages do it, by not having UB on their language standard to start with. If people prefer "performance trumps correctness" and "winning compiler benchmarks is what counts" then they should happily keep getting exploited.
- dom0 9y agoI do see your point, but that'd be a different language. With the standardised C we have, it's not easy.
- pjmlp 9y agoWhich is why we should move away from it. However I don't see it ever happening in the UNIX world, only on OSes whose architecture is not bound to the traditional UNIX/C culture. Which is why see as positive that Apple, Google and Microsoft are pushing C and C++ down into the very lowest layers of their OS stacks, mostly visible on Google's case. Even straight pure Assembly programming has less UB surprises.
- gpderetta 9y ago> It is very easy to be efficiently determined at compile time for many cases it is in fact equivalent to the halting problem. What you can do is check at runtime, which has performance implications (from trivial to expensive depending on the check).
- pjmlp 9y agoNot if the language standard doesn't allow for UB to begin with, then there isn't any halting problem to worry about. This is what the alternatives in the memory safe systems programming language since Algol days do. Surely they still allow for developers to disable some of those checks explicitly, but then it is the programmers fault to choose "performance trumps correctness" instead of "correctness trumps performance".
- caf 9y agoIt doesn't matter if the language defines the behaviour of, say, offsetting an array beyond its declared bounds. That doesn't change the general undecidability of statically proving the offset will always be within the bounds at compile-time - in other words, you need runtime checks in some cases (it's just a matter of whether the compiler or the programmer supplies them).
- eru 9y agoNah, with some help from the programmer, you can produce those proofs. It's not too hard. The halting problem is impossible to solve for arbitrarily evil programs, but that doesn't mean that it's impossible to write programs that are easy to analyse.
- gpderetta 9y agoI think that statically guaranteeing something like in-bound indexing or absence of division by zero you need depended types, which is not exactly easy nor mainstream. And even with dependent types, many non-evil, otherwise correct programs will be rejected.
- yorwba 9y agoAren't dependent types able to express any statement formalizable in predicate logic? This should include most things you might want to say about the correctness of non-evil programs. I think the real problem with them is that type-checking itself becomes undecidable, so you get the additional problem of proving that your program is indeed correctly typed.
- eru 9y agoYes, for the general problem you want dependent types (or similar). There are middle grounds, of course: you can let the compiler figure out on its own what it can, and let it insert runtime checks for the other cases. And add some way for the programmer to declare that eg "warn me if this can't be optimized" or "trust me, this is safe" or even "here's a proof for you". But in any case, dependent types are possible---undecidability is not a hard barrier here.
- jabot 9y ago"Very easy" - well, if you think garbage collection is easy... And yes, if you want to allow manual allocation of objects and setting pointers to arbitrary objects, then your two choices are: 1) garbage collection 2) undefined behavior (use-after-free, double-free, dangling pointers, etc.)
- pjmlp 9y ago> garbage collection is easy... Garbage collection isn't the only way of writing mostly safe systems programs. ESPOL, NEWP are 10 year older than C. PL/8 was the systems programming language used by IBM for their first RISC mainframe, followed by PL/S. Mesa used at Xerox PARC. Modula-2 used at ETHZ and many 16 bit systems. Object Pascal used to write the first versions of Mac OS and Lisa. Ada and SPARK used by high integrity systems where human lives can be at risk. All of them with not even a quarter of C's UB collection.
- jabot 9y agoWell, I don't know about half of these programming languages. However: - ADA requires garbage collection - Modula-2 and Object pascal have manual memory management, i.e.: "new" and "delete" - together with double-free, use-after-free, and dangling pointers... I agree that C is by far worse, but please recognize that at least some of the undefined behavior problems are really hard to solve. EDIT: Oh, and we haven't started talking about multi threading yet, have we?
- pjmlp 9y agoWhat about learning to understand English? "writing mostly safe systems programs." Do you understand what mostly means? Ada and Modula-2 have multi-threading as part of their ISO/ANSI language standard. Also you don't seem to know much about Ada given your GC remark, but here is some learning. https://archive.fosdem.org/2016/schedule/event/ada_memory/ https://archive.fosdem.org/2016/schedule/event/ada_memory/ Of course there are still use cases where Algol derived languages are still unsafe, however those use cases are a tiny portion of what happens in C land.