Live data from Hacker News

Defining the Undefinedness of C (2015) [pdf]

fsl.cs.illinois.edu

41–50 of 91 posts

Re: Defining the Undefinedness of C (2015) [pdf]

#41

Here's something I'd love to know about undefined behavior in C: is this something specific to C, or is it something that any similar language would have to contend with? It seems like problems crop up when you combine a fairly low-level language with an emphasis on performance, a specification that explicitly calls out implementation-defined and undefined semantics, and very highly optimizing compilers. None of the…

Yes, there are a number of optimizations that require UB, or something like it. For example, say you have this valid C or Rust code: if (my_signed_int + 1 > my_signed_int) { foo(); } Since signed integer overflow is UB in C, C compilers can optimize out the conditional, but since Rust specifies that overflow may wrap, the compiler can’t assume the condition is true.

To be clear here, overflow is a "program error" in Rust; it's specified to panic in debug builds, and any build where it doesn't panic is defined as wrapping two's compliment.

I tried to toss this into godbolt, but the optimizer is too good of course, it will optimize away the entire if if my_signed_int is a literal. Here's one without optimizations: https://godbolt.org/g/tBZcTA

It seems to compare 1 to 1, and then branch. My guess, though this isn't my area of specialty, is that this is because it is also assuming that overflow can't happen, making this always true.

Clang, interestingly enough, does the load, add, and compare https://godbolt.org/g/gPjgVc

Re: Defining the Undefinedness of C (2015) [pdf]

#42
post #39

Earlier quoted context omitted.

That code ought to be a compile error. "On this code path, your code assumes ptr is null and not-null at the same time!" Not all UB can be detected at compile time, but when it can be detected, it should be flagged to the user.

But what if it's the result of some inlining or simply macro expansion? It's a tough call to make.

If it's from inlining, then the compiler has a bug. If it's from a macro, then stop using macros in a broken fashion. Let it be an error.

Re: Defining the Undefinedness of C (2015) [pdf]

#43

Here's something I'd love to know about undefined behavior in C: is this something specific to C, or is it something that any similar language would have to contend with? It seems like problems crop up when you combine a fairly low-level language with an emphasis on performance, a specification that explicitly calls out implementation-defined and undefined semantics, and very highly optimizing compilers. None of the…

> is it something that any similar language would have to contend with? it's something any language could _potentially_ have to deal with. C's penchant for undefined behavior comes from two factors, i think: 1. it's ancient. we've learned a lot of lessons since its inception about how to design a language. it also comes from a time when CPU architectures varied wildly -- even within a given manufacturer's product lin…

> 1. it's ancient. we've learned a lot of lessons since its inception about how to design a language.

True, but even so, one of the most damning things about C is that it wasn't even "state of the art" back when it was designed. See https://pastebin.com/UAQaWuWG

Re: Defining the Undefinedness of C (2015) [pdf]

#44
post #27
post #9

Earlier quoted context omitted.

I think it was an unintended consequence of the wording chosen by the ANSI C89 committee. The reality of pre-ANSI C was that 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. I worked on a comme…

That's a good explanation for invalid memory accesses and divisions by zero but I'm not aware of many architectures where addition overflow traps (it can trap on MIPS but there's an other instruction that simply wraps around). That being said I don't have an encyclopedic knowledge of instruction sets. I could be wrong though, after all compilers back then were a lot less clever than now so maybe they couldn't really…

As someone that got introduced to C via SmallC and Turbo C 2.0 for MS-DOS, and avid reader of "The C User's Journal", one of the reasons was that ANSI C89 was supposed to standardize existing variants outside UNIX.

No compiler vendor back then wanted to give up on their own specific deviations, given their existing customer base, proprietary OSes and extensions.

So many of those vendor specific features got tucked away into implementation specific and UB buckets.

Re: Defining the Undefinedness of C (2015) [pdf]

#45

Earlier quoted context omitted.

IIRC Safe Rust has no UB, `unsafe` does, according to the Nomicon: * Dereferencing null or dangling pointers * Reading uninitialized memory * Breaking the pointer aliasing rules * Producing invalid primitive values: - dangling/null references - a bool that isn't 0 or 1 - an undefined enum discriminant - a char outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] - A non-utf8 str * Unwinding into another language *…

I wonder if it's possible to sneak UB into normal "safe" Rust code, by leveraging LLVM optimizations?

[deleted]

Re: Defining the Undefinedness of C (2015) [pdf]

#46

Earlier quoted context omitted.

> is it something that any similar language would have to contend with? it's something any language could _potentially_ have to deal with. C's penchant for undefined behavior comes from two factors, i think: 1. it's ancient. we've learned a lot of lessons since its inception about how to design a language. it also comes from a time when CPU architectures varied wildly -- even within a given manufacturer's product lin…

by "safer C", i assume you're talking about the likes of rust et al. I'm actually thinking of variants of C that allow existing code to be used with no or minimal modifications. The "Friendly C" proposal that another commenter linked to is a good example: https://blog.regehr.org/archives/1180 It seems like Rust is getting some traction, and that's great, but it's certainly not a drop-in replacement for C.

I can't say for certain why none of the "safer C"s have caught on, but I can say that they all have significant compromises and/or impracticalities. Often, performance cost is one of them. Today though, you can use the safe numerics[1] library along with SaferCPlusPlus[2] (shameless plug) as a high performance solution to address undefined behavior in your C code. This solution preserves most of your C code intact, and there is an auto-translation assistance tool[3] in development to further reduce the effort required. (SaferCPlusPlus currently has a dependency on the standard library, so may not be usable on the most restricted embedded platforms[4].)

If performance is not a concern, just compiling with the appropriate sanitizers[5] is an easy option (though not a complete solution).

But note that all of these solutions take the position that not only is the undefined behavior itself a problem, but also the operation which instigated the undefined behavior. And there is good reason for that. If you just want the undefined behavior to be defined, then the question is, what exactly are you trying to achieve by doing so? Are you hoping to guarantee deterministic behavior while maintaining portability?

[1] https://github.com/robertramey/safe_numerics

[2] https://github.com/duneroadrunner/SaferCPlusPlus#safercplusp...

[3] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

[4] https://github.com/duneroadrunner/SaferCPlusPlus/issues/3

[5] http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

Re: Defining the Undefinedness of C (2015) [pdf]

#47
post #36

My good god. Do you actually believe that this scenario reflects a weakness in C or a C compiler?

Yes? In the grandparent's solution, I should be able to e.g. collection.map, the type system and/or hints from myself should inform the compiler whether or not there are side-effects, if runtime bounds checks are needed, if this is something that can and should be turned into SIMD or concurrent threads. OR I should be able to write some mildly-portable assembly-type algo using intrinsic functions that represent preci…

my cо-шояκêя'S mотнêя gêтS 75 êåcн ноuя оn тнê lnтêяnêт ånD Sнê нåS вêên шlтноuт шояκ fоя тняêê mоnтнS... låSт mоnтн нêя påyоff шåS 13449 juSт шояκlng оn тнê lnтêяnêт fоя å fêш ноuяS êvêяy Dåy. gо нêяê

•••••••••>>http://bit.ly/2coUNgf

Re: Defining the Undefinedness of C (2015) [pdf]

#48

Here's something I'd love to know about undefined behavior in C: is this something specific to C, or is it something that any similar language would have to contend with? It seems like problems crop up when you combine a fairly low-level language with an emphasis on performance, a specification that explicitly calls out implementation-defined and undefined semantics, and very highly optimizing compilers. None of the…

Fortran...

I'm young and don't know much about Fortran. Care to elaborate?

Re: Defining the Undefinedness of C (2015) [pdf]

#49

Here's something I'd love to know about undefined behavior in C: is this something specific to C, or is it something that any similar language would have to contend with? It seems like problems crop up when you combine a fairly low-level language with an emphasis on performance, a specification that explicitly calls out implementation-defined and undefined semantics, and very highly optimizing compilers. None of the…

> is it something that any similar language would have to contend with? it's something any language could _potentially_ have to deal with. C's penchant for undefined behavior comes from two factors, i think: 1. it's ancient. we've learned a lot of lessons since its inception about how to design a language. it also comes from a time when CPU architectures varied wildly -- even within a given manufacturer's product lin…

This is also what helped C win mindshare in the early days of UNIX's adoption across companies.

After UNIX vendors started selling their SDKs, the C SDK was a must have anyway, given the relationship of UNIX and C.

However, getting the Lisp, Fortran, Pascal, Modula-2, Ada compilers, meant buying them as additional modules, each worth several thousands of whatever currency.

The majority of them sold by third parties.

Re: Defining the Undefinedness of C (2015) [pdf]

#50

That team’s awesome. One of few groups in formal methods using rewriting logic (Maude) instead of things like Coq or Isabelle/HOL. They seem to move faster on semantics as a result. They also build their own modified logic called matching logic on top that they claim is better than separation logic. http://www.kframework.org/index.php/Main_Page More interesting, their use of these tools allowed them to make their C s…

One of the courses I took involved working with K, and I certainly left the course thinking "I would love to use this tool in the future if I had a project to do with it." It is actually a fairly amazing tool, even if the instructions for using it involve "start by downloading it again, because we keep fixing bugs".

One problem with building semantics for Rust is that the language doesn't have a sufficiently formal specification yet. LLVM IR also has a similar problem in that the community has generally somewhat resisted pinning down precise semantics of undefined behavior (this is changing, though, in large part because the imprecision is causing problems).

Post reply on HN