Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ What is the earliest undefined behavior can manifest itself?

I'm aware that undefined behavior can potentially cause anything, which makes any program containing UB potentially meaningless. I was wondering if there is any way to identify the earliest point in a program that undefined behavior could cause problems. Here is an example to illustrate my question.

void causeUndefinedBehavior()
{
   //any code that causes undefined behavior
   //every time it is run
   char* a = nullptr;
   *a;
}


int main()
{
 //code before call
 //...
 causeUndefinedBehavior();
 //code after call
 //...
}

From my understanding, the possible times undefined behavior could be evoked (not necessarily manifested) are:

  1. When causeUndefinedBehavior() is compiled.
  2. When main() is compiled.
  3. At the time the program is run.
  4. At the time causeUndefinedBehavior() is executed.

Or is the point where undefined behavior is evoked completely different for every case and every implementation?

In addition, if I commented out the line where causeUndefinedBehavior() is called, would that eliminate the UB, or would it still be in the program since code containing UB was compiled?

like image 390
Elliot Hatch Avatar asked Oct 29 '12 00:10

Elliot Hatch


4 Answers

As your code somewhat demonstrates, undefined behavior is almost always a condition of runtime state at the time the behavior is attempted. A slight modification of your code can make this painfully obvious:

void causeUndefinedBehavior()
{
   //any code that causes undefined behavior
   //every time it is run
   char* a = nullptr;
   *a;
}


int main()
{
 srand(time(NULL));
 //code before call
 //...
 if (rand() % 973 == 0)
    causeUndefinedBehavior();
 //code after call
 //...
}

You could execute this a thousand times or more and never trip the UB execute-condition. that doesn't change the fact the function itself is clearly UB, but detecting it at compile time in context of the invoker is not trivial.

like image 161
WhozCraig Avatar answered Nov 18 '22 16:11

WhozCraig


I think it depends on the type of undefined behavior. Things that would affect something like structure offsets could cause undefined behavior, which would show up any time code that touches that structure is executed.

In general, however, most undefined behavior happens at run time, meaning only if that code is executed will the undefined behavior occur.

For example, an attempt to modify a string literal has undefined behavior:

char* str = "StackOverflow";
memcpy(str+5, "Exchange", 8);    // undefined behavior

This "undefined behavior" will not take place until the memcpy executes. It will still compile into perfectly sane code.

Another example is omitting the return from a function with a non-void return type:

int foo() {
    // no return statement -> undefined behavior.
}

Here, it is at the point at which foo returns that the undefined behavior occurs. (In this case, on x86, whatever happened to be in the eax register is the resultant return value of the function.)

Many of these scenarios can be identified by enabling the a higher level of compiler error reporting (eg. -Wall on GCC.)

like image 21
Jonathon Reinhart Avatar answered Nov 18 '22 14:11

Jonathon Reinhart


while it is "undefined behaviour", given a particular compiler, it will have a predictable behavior of some sort. But because it is undefined, on different compilers, it may result in that behavior occurring at any point of the complilation / runtime

like image 1
Keith Nicholas Avatar answered Nov 18 '22 16:11

Keith Nicholas


"Undefined behavior" means that the language definition doesn't tell you what your program will do. That's a very simple statement: no information. You can speculate all you like about what your implementation may or may not do, but unless your implementation documents what it does, you're only guessing. Programming isn't about guessing; it's about knowing. If the behavior of your program is undefined, fix it.

like image 2
Pete Becker Avatar answered Nov 18 '22 14:11

Pete Becker