Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Is there a possibility there will be introduced a new rule saying "if the compiler detects an UB it should abort the compilation instead of breaking the code in the most incomprehensible way possible"?

Right now it's just scary to start a new project in C. It would be really great if there was more emphasis on correctness of the produced code instead of the insane optimizations.



This can only be done at compile time in very specific cases. The huge problem here is the compiler has no way of knowing which cases of undefined behavior are bugs in the program and which cases of undefined behavior are just examples of unreachable code. If the compiler aborted compilation when it detected undefined behavior, you’d be getting a lot of false positives for unreachable code, and you’d need to solve that problem (figuring out how to generate sensible errors and suppress them). This is not even remotely easy.

If you are concerned about safety there are ways to achieve that, like using MISRA C, formally verifying your C, or by writing another language like Rust.


Good point, but could it not be required that the unreachable code would be annotated to be unreachable? It could even have a (development only) assertion in the location.


That would be an immense undertaking. It’s not really just that some statement or expression is unreachable (we have __builtin_unreachable() in GCC for stuff like that) but that certain states are unreachable.

For example,

    int buffer_len(struct buffer *buf) {
        return buf->end - buf->start;
    }
There are at least three states that trigger undefined behavior: buf is not a valid pointer, buf->end - buf->start doesn’t fit in int, and buf->end and buf->start don't point to the same object.

I’m not sure how you would annotate this. At the function call site, you would somehow need to show that buf is a valid pointer, and that start/end point to same object and the difference fits in an int. It would start looking more like Coq or Agda than C.

Honestly, I think if you really want this kind of safety, your options are to use formal methods or switch to a different language.

There’s also this weird assumption here that the compiler detects undefined behavior in your program and then mangles it. It’s really the opposite—the compiler assumes that there is no undefined behavior in your program, and optimizes accordingly. In practice you can turn optimizations off and get something much closer to the “machine model” of C (which doesn’t really exist anyway) but most people hate it because their code is too slow.


Thanks, so it's definitely easier said than done! Good explanation.


> If the compiler aborted compilation when it detected undefined behavior, you’d be getting a lot of false positives for unreachable code

Could you please provide an example of this?


Overflow of signed integers is undefined.

    int add(int a, int b) { return a + b; }
Unless the compiler can prove that `add` is never called with a and b values resulting in an overflow, this code can lead to UB, and, under your rules, the compilation aborts.


It would be wonderful (IMO) if we could get to that point, but that would leave implementations with too great of a burden because many forms of UB can only be caught at runtime (without a considerable number of false positives). Generally, the C committee makes things a "constraint violation" (aka, we would like implementations to err) whenever something can be caught at compile time, and we leave the undefined behavior hammer for scenarios where there is not a reasonable alternative.

Thankfully, there are a lot of tools to help developers catch UB these days (UBSan, static analyzers, valgrind, etc). I would recommend using those tools whenever starting a new project in C (or C++, for that matter).


  int i;
  […]
  i += 1;
potentially is undefined behavior; i could overflow.

Compilers nowadays are fairly good at warning about definite undefined behavior.

I don’t think anybody would be happy with a compiler that aborted on all potential undefined behavior. That would (almost) be equivalent to banning the use of all signed ints.


Some implementations have been making a lot of effort to do just that. GCC in particular has been adding these types of checks (either as warnings or sanitizers) in recent years and although there is still much to improve I'd like to think we have made good progress.

Adding a rule requiring implementations to error out in cases of undefined behavior would be hard to specify in the standard. It could (and in my view should) be done by providing non-normative encouragement as "Recommended Practice."


Try using "lint" or other code checkers.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: