Search code examples
c++clangllvmfreebsdllvm-clang

Why does my C++ program crash when I forget the return statement, rather than just returning garbage?


I've started using CLang recently to compile embedded C++ ARM programs.

Prior to this I used GCC and C, almost exclusively for embedded work.

I've noticed that when I have a method that returns a value, and I forget the return statement, the program core dumps. There is no error printed other than "msleep error -1" from one of my device drivers. This is on FreeBSD.

I would expect that forgetting the return statement would just result in garbage being returned from the function, not a core dump.

EDIT: I'm returning a bool, not a pointer or object or anything complicated. The program crashes even when the return value doesn't matter.

What is going on?

E.G.:

bool MyClass::DummyFunc() {
  <do some stuff and forget the return value>     
}

Elsewhere:

if(pMyObj->DummyFunc()) {
  print ("Hey, it's true!\n");
} else {
  print ("Darn, it's false!\n");
}

That code should not crash, regardless of the return value.


Solution

  • Forgetting the return value results in the control flow reaching the end of a function. The C and C++ standards both describe this case. Note that main is an exception to this case and is described separately.

    Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function C++11 Draft pg 136

    My experience with clang has been that the compiler will treat instances of "undefined behavior" as will not happen and optimize away the paths. Which is legal, since the behavior is undefined. Often clang will instead emit an illegal instruction along the omitted path so that the code will crash if the "impossible" happens, which is likely your case here. In fact, the compiler could then determine that calling DummyFunc() results in undefined behavior and therefore cannot happen, and instead start optimizing away the calling bodies.

    gcc is far "friendlier" and tries to generate something nice, such as returning 0.

    Note, both compilers are correct and are producing valid code according to the standard.