Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is undefined behavior worth it?

Many bad things happened and continue to happen (or not, who knows, anything can happen) due to undefined behavior. I understand that this was introduced to leave some wiggle-room for compilers to optimize, and maybe also to make C++ easier to port to different platforms and architectures. However the problems caused by undefined behavior seem to be too large to be justified by these arguments. What are other arguments for undefined behavior? If there are none, why does undefined behavior still exist?

Edit To add some motivation for my question: Due to several bad experiences with less C++-crafty co-workers I have gotten used to making my code as safe as possible. Assert every argument, rigorous const-correctness and stuff like that. I try to leave as little room has possible to use my code the wrong way, because experience shows that, if there are loopholes, people will use them, and then they will call me about my code being bad. I consider making my code as safe as possible a good practice. This is why I do not understand why undefined behavior exists. Can someone please give me an example of undefined behavior that cannot be detected at runtime or compile time without considerable overhead?

like image 691
Björn Pollex Avatar asked May 05 '10 09:05

Björn Pollex


People also ask

Why does undefined behavior exist?

Undefined behavior exists mainly to give the compiler freedom to optimize. One thing it allows the compiler to do, for example, is to operate under the assumption that certain things can't happen (without having to first prove that they can't happen, which would often be very difficult or impossible).

Why does C++ have so much undefined behavior?

C and C++ have undefined behavior, because nobody's defined an acceptable alternative that allows them to do what they're intended to do. C# and Java take a different approach, but that approach fits poorly (if at all) with the goals of C and C++.

Is unspecified behavior undefined behavior?

Unspecified behavior is different from undefined behavior. The latter is typically a result of an erroneous program construct or data, and no requirements are placed on the translation or execution of such constructs.

What is UB programming?

In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres.


2 Answers

I think the heart of the concern comes from the C/C++ philosophy of speed above all.

These languages were created at a time when raw power was sparse and you needed to get all the optimizations you could just to have something usable.

Specifying how to deal with UB would mean detecting it in the first place and then of course specifying the handling proper. However detecting it is against the speed first philosophy of the languages!

Today, do we still need fast programs ? Yes, for those of us working either with very limited resources (embedded systems) or with very harsh constraints (on response time or transactions per second), we do need to squeeze out as much as we can.

I know the motto throw more hardware at the problem. We have an application where I work:

  • expected time for an answer ? Less than 100ms, with DB calls in the midst (say thanks to memcached).
  • number of transactions per second ? 1200 in average, peaks at 1500/1700.

It runs on about 40 monsters: 8 dual core opteron (2800MHz) with 32GB of RAM. It gets difficult to be "faster" with more hardware at this point, so we need optimized code, and a language that allows it (we did restrain to throw assembly code in there).

I must say that I don't care much for UB anyway. If you get to the point that your program invokes UB then it needs fixing whatever the behavior that actually occurred. Of course it would be easier to fix them if it was reported straight away: that's what debug builds are for.

So perhaps that instead of focusing on UB we should learn to use the language:

  • don't use unchecked calls
  • (for experts) don't use unchecked calls
  • (for gurus) are you sure you really need an unchecked call here ?

And everything is suddenly better :)

like image 179
Matthieu M. Avatar answered Oct 20 '22 12:10

Matthieu M.


My take on undefined behavior is this:

The standard defines how the language is to be used, and how the implementation is supposed to react when used in the correct manner. However, it would be a lot of work to cover every possible use of every feature, so the standard just leaves it at that.

However, in a compiler implementation, you can't just "leave it at that," the code has to be turned into machine instructions, and you can't just leave blank spots. In many cases, the compiler can throw an error, but that's not always feasible: There are some instances where it would take extra work to check whether the programmer is doing the wrong thing (for instance: calling a destructor twice -- to detect this, the compiler would have to count how many times certain functions have been called, or add extra state, or something). So if the standard doesn't define it, and the compiler just lets it happen, witty things can sometimes happen, maybe, if you're unlucky.

like image 39
Carson Myers Avatar answered Oct 20 '22 12:10

Carson Myers