Live data from Hacker News

Undefined Behavior in 2017

blog.regehr.org

91–100 of 120 posts

Re: Undefined Behavior in 2017

#91
post #61

Earlier quoted context omitted.

But the optimizer doesn't give up in this case. It successfully figures out that the loop has no side effect except heating up your processor and eliminates it.

What's the advantage of eliminating the loop? If the compiler is able to do that analysis, why not flag the endless spin loop as a compilation error?

effectively a no-op... isn't code after inf-loop also removed as it is considered unreachable?

Re: Undefined Behavior in 2017

#92
post #22

The main message from my point of view: > Be knowledgeable about what’s actually in the C and C++ standards since these are what compiler writers are going by. Avoid repeating tired maxims like “C is a portable assembly language” and “trust the programmer.” > Unfortunately, C and C++ are mostly taught the old way, as if programming in them isn’t like walking in a minefield. Nor have the books about C and C++ caught u…

I think it's the compilers that have perverted the language to such an extent that it's become ridiculously difficult to understand, and so it's the compilers that must change back to being less obtuse and adversarial. The C standard even suggests, when defining undefined behaviour, that one of the possible options is "behaving during translation or program execution in a documented manner characteristic of the envir…

The original mandate of X3J11 was to “codify common existing practice”. The published Rationale goes on to describe a number of relevant criteria, including

• Existing code is important, existing implementations are not.

• Avoid “quiet changes.”

• Trust the programmer.

• Keep the language small and simple.

• Make it fast, even if it is not guaranteed to be portable.

In pre-ANSI C, and C89 C interpreted in line with the Rationale, if you wrote ‘+’, the expectation was that you'd get the target machine's ‘add’ instruction, no more and no less. It might overflow, it might not; it might crash or hang your machine on overflow or trap values — but that is all your problem, not the language's or compiler's. The ANSI invention of ‘undefined behaviour’ can be considered a good-faith attempt to codify things like this, but botching it was one of the two great failures of C89.

I worked on a commercial compiler at the time, and I'm confident no one thought of C89 as a license to screw the customer.

Re: Undefined Behavior in 2017

#93
post #69
post #68

Earlier quoted context omitted.

I can't tell if this is satirical, but to be clear, you're proposing to disallow addition?

Rather define the behaviour of what happens when addition of two ints exceed the maximum allowed value.

You're changing your plan here. Maybe you could at least concede that the issue of UB is difficult and is not going to be solved by saying "why don't they just" on HN?

Re: Undefined Behavior in 2017

#94
post #76

Earlier quoted context omitted.

Nah, 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.

I 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.

Aren'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.

Re: Undefined Behavior in 2017

#96
post #46

> Loops that Neither Perform I/O nor Terminate > Summary: This UB is probably not a problem in practice (even if it is moderately displeasing to some of us). Since LLVM is mostly based around C/C++ semantics this actually turned out to be a problem for rust, because rust can encode diverging functions in its type system and assume certain code sections to be unreachable. If the compiler then optimizes out code and th…

At least according to https://github.com/rust-lang/rust/issues/28728#issuecomment-... this is a more general issue with clang/llvm -- even e.g. `while(1);` in C is being optimized out.

Re: Undefined Behavior in 2017

#97
post #78

Earlier quoted context omitted.

They CAN accommodate all users, just have compile time options you can enter in your make file/on the command line/etc to say what level of bounds checking/etc you want compiled into your code. Hell that way even within a given project you can choose "this library I'm nervous about so I'll eat the hit on bounds checking".

They do it, but the performance culture among C devs doesn't appreciate enabling them. https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Object-Size-Che... https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Pointer-Bounds-... I bet not much UNIX software compiled with gcc enables them. Android is probably the only OS that does make use of them. https://android-developers.googleblog.com/2017/04/fortify-in...

The performance culture isn't just C. Far from it.

Rust was susceptible to Stack Clash because they ripped out their existing stack probing to gain a few percent increase in performance.

The article for this thread literally says, "For many use cases ASan is the better choice because it has much less overhead." IME Valgrind does a _much_ better job of detecting memory issues, partly because ASan only detects issues directly triggered in the code that you compile, whereas Valgrind can detect memory issues directly triggered by external code, but indirectly caused by your code.

Re: Undefined Behavior in 2017

#98
post #10
post #8

Earlier quoted context omitted.

Some undefined behaviours relate to runtime values. !iirc! signed 2+2 is safe but signed SIGNED_INT_MAX + 1 is not.

But it is easy to give it a defined behavior on a particular architecture. For example, on x86-64, it can be defined to overflow just like unsigned does. The compiler can emit errors about the code if it is compiled to a different architecture where the same defined behavior is too expensive to implement.

It can be, but it isn't. All contemporary ISAs use two's complement arithmetic for signed integers, including x86-64, and so I think signed overflow could be made well defined on all archs without particularly disadvantaging one arch over the other.

The reason that that doesn't happen, here as elsewhere, is that there are a number of specific compiler optimizations that rely on it being undefined. See GCC's -fwrapv flag.

Re: Undefined Behavior in 2017

#99
post #22

The main message from my point of view: > Be knowledgeable about what’s actually in the C and C++ standards since these are what compiler writers are going by. Avoid repeating tired maxims like “C is a portable assembly language” and “trust the programmer.” > Unfortunately, C and C++ are mostly taught the old way, as if programming in them isn’t like walking in a minefield. Nor have the books about C and C++ caught u…

I think it's the compilers that have perverted the language to such an extent that it's become ridiculously difficult to understand, and so it's the compilers that must change back to being less obtuse and adversarial. The C standard even suggests, when defining undefined behaviour, that one of the possible options is "behaving during translation or program execution in a documented manner characteristic of the envir…

> I think it's the compilers that have perverted the language to such an extent that it's become ridiculously difficult to understand, and so it's the compilers that must change back to being less obtuse and adversarial.

I disagree. Undefined behavior is very important for optimization. See John Regehr's blog post on the topic [1], or any of DannyBee's numerous posts here explaining why GCC and Clang can and must exploit UB, etc. etc.

[1]: https://blog.regehr.org/archives/1467

Re: Undefined Behavior in 2017

#100

Earlier quoted context omitted.

See also https://doc.rust-lang.org/nomicon/working-with-unsafe.html > unsafe does more than pollute a whole function: it pollutes a whole module. Generally, the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy.

Not to belabor the point, but... > the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy I understand how this is meant in the context of that page, and it is true that modules protect against users messing with modules' internal invariants. But does that also work the other way around? In the example in https://gankro.github.io/blah/only-in-rust/#unbound-lifetime... it's…

I would argue that this is not the caller making the mistake; it's this function. That is, since this function is safe, any safe code should be able to call it and not generate UB. It's not the caller's fault here, it's the incorrect implementation.
Post reply on HN