Defining the Undefinedness of C (2015) [pdf]
fsl.cs.illinois.edu
Defining the Undefinedness of C (2015) [pdf]
1–10 of 91 posts
Re: Defining the Undefinedness of C (2015) [pdf]
#2It 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 "safer C" languages seems to have gained much traction. Is that because the problem really is intractable, or just because maintaining a decent level of compatibility with C is too hard? The major selling point of a safer C is being able to reuse lots of existing C code, after all.
Note that other languages probably have the same pitfalls, just latent for now -- their specs are silent about undefined operations, or they don't have specs at all, and their compilers don't optimize as aggressively as GCC or Clang.
Re: Defining the Undefinedness of C (2015) [pdf]
#3Here'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…
Re: Defining the Undefinedness of C (2015) [pdf]
#4Here'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…
Some CPU ABI even have instructions which, when used with certain operands, are undefined. For instance the ARM Thumb "BL" instruction is encoded as two successive "pseudo-instructions", IIRC if you break the pair the behaviour is undefined. There are other instructions which are either undefined of implementation-defined, in particular instructions which attempt to load or store the PC register.
C takes it a bit over the top, for instance overflow doesn't have to be undefined behaviour (it could be left as implementation-defined for instance, which is a lot less nasty).
Re: Defining the Undefinedness of C (2015) [pdf]
#5Here'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…
How similar is similar? Pascal? Ada? Spark Ada? Rust? Friendly C (https://blog.regehr.org/archives/1180)?
Re: Defining the Undefinedness of C (2015) [pdf]
#6Here'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…
One example that comes to mind is looping over each element in an array. C doesn't actually have this concept in the language. Instead, you use an idiom that's so common that you'll read it as looping over an array:
for (int i=0; i
The compiler can also read this common idiom and find out that it's going to be doing a bunch of sequential memory accesses, which it can optimize. That's great. Except, what if the pointer arr is near the maximum value for its type and it'll overflow when you add i times the size of the array element to it? Then you're doing some very non-sequential accesses.This doesn't make sense in context: you wouldn't have an array that's split across the end and the beginning of addressable memory. You'd rather ignore that case so you can optimize the really, really common case of iterating over an array.
But a better-designed language can give you a way to just say "for each element in this array".
Rust aims to be as efficient as C, but does not have the goal of letting you directly reuse C code. Its surface of UB is much smaller than C's, and easier to define, because the language is more expressive of what you actually intend to do.
Re: Defining the Undefinedness of C (2015) [pdf]
#7Here'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…
Any language which allows unprotected memory access will potentially have "undefined behaviour" if you start plowing through random addresses. Things like divisions by 0 are also commonly UB. Some CPU ABI even have instructions which, when used with certain operands, are undefined. For instance the ARM Thumb "BL" instruction is encoded as two successive "pseudo-instructions", IIRC if you break the pair the behaviour…
Re: Defining the Undefinedness of C (2015) [pdf]
#8Here'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…
Probably the majority of languages are philosophically the same as Go; in single-threaded operation there's not much undefined behavior, but once you go multithreaded and have a data race, all bets are off. The "memory model" document is not very precise, but mostly states that if you avoid data races, things will be ok.
All languages with FFI to C, of course, inherit C's approach to undefined behavior through that mechanism.
Re: Defining the Undefinedness of C (2015) [pdf]
#9Here'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…
Re: Defining the Undefinedness of C (2015) [pdf]
#10Here'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…
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 line.
2. the developer culture during the time when C was being designed was of the "i don't want a language to tell me how to write code. if it's possible in assembly, i want to be able to do it in C." mentality.
> is that because the problem really is intractable?
by "safer C", i assume you're talking about the likes of rust et al.
C is used largely in the embedded space, and the embedded space, i think, is notoriously stuck in their ways. most embedded projects accrue a lot of third-party code (the kernel being a big one) and that code is written in C. so you already need C developers. why wander into unexplored territory, especially when it's at the cost of an additional necessary skill from your developers?