Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit the confusion caused by undefined-behavior?

As I understand from my reading, undefined-behavior is the result of leaving the compiler with several non-identical alternatives at compile time. However, wouldn't that mean that if one were to follow strict coding practice (like putting each assignment and each equality in a separate statement, proper debugging and commenting) then it shouldn't pose a significant problem in finding the source of the undefined-behavior.

Further, there are, for each error that comes up, if you identify the code, you should know what statements can be used in that particular statement's stead, correct?

EDIT: I'm not interested in places where you have written code that you didn't mean to write. I'm interested in examples where code that is sound by mathematical logic fails to work.

Also, I consider 'good coding practice' to be strong informative comments every few lines, proper indentation, and debugging dumps on a regular basis.

like image 807
Ritwik Bose Avatar asked Jan 12 '10 05:01

Ritwik Bose


1 Answers

Undefined behavior isn't necessarily leaving the compiler with multiple alternatives. Most commonly it is simply doing something that doesn't make sense.

For example, take this code:

int arr[2];
arr[200] = 42;

this is undefined behavior. It's not that the compiler was given multiple alternatives to choose from. it's just that what I'm doing does not make sense. Ideally, it should not be allowed in the first place, but without potentially expensive runtime checking, we can't guarantee that something like this won't occur in our code. So in C++, the rule is simply that the language specifies only the behavior of a program that sticks to the rules. If it does something erroneous like in the above example, it is simply undefined what should happen.

Now, imagine how you're going to detect this error. How is it going to surface? It might never seem to cause any problems. Perhaps we just so happen to write into memory that's mapped to the process (so we don't get an access violation), but is never otherwise used (so no other part of the program will read our garbage value, or overwrite what we wrote). Then it'll seem like the program is bug-free and works just fine.

Or it might hit an address that's not even mapped to our process. Then the program will crash immediately.

Or it might hit an address that's mapped to our process, but at some point later will be used for something. Then all we know is that sooner or later, the function reading from that address will get an unexpected value, and it'll behave weird. That part is easy to spot in the debugger, but it doesn't tell us anything about when or from where that garbage value was written. So there's no simple way to trace the error back to its source.

like image 74
jalf Avatar answered Oct 10 '22 03:10

jalf