Don’t underestimate compiler warnings Link to heading

Yesterday, I was working on some C++ project and stumbled upon a very strange behavior. For some input, the program crashed with a scary message:

Image

What did I do wrong? I don’t even know how to generate this intentionally! I have seen abnormal program exits with exceptions, but I haven’t really experience this hideous error message. Debugging this wasn’t easy, as the problematic line pointed by the debugger looked perfectly normal to me. Maybe I have been focusing exclusively on Rust recently and my C++ skills have become too Rusty?

After spending more time than I probably should, I finally figured it out, and the answer has been there in the compiler’s warning. But hey, who cares about the warnings, especially during the prototyping phase where you just want to run the program as quickly as possible and worry about stupid warnings later? After all, warning is a warning — as long as it compiles we are good, right?

Well, I guess I was wrong. Though most of the warnings from gcc or clang are not critical, hence warnings and not errors, there are some warnings that are critical enough that I feel like they should be promoted(?) as errors, such as this:

Image

I omitted a return value for one of the functions I had. Believe me, it was not as silly as it sounds. I just missed one of the conditional branches I didn’t expect it could happen. That’s still my fault, but things happen. I actually blame the compiler — the compiler should simply disallow this and raise compilation error, rather than just a warning.

If you are interested in a concrete example, here is a minimal code snippet

#include <stdio.h>

int first_word_length(char const *sentence) {
  char const* cur = sentence;
  while (char c = *cur) {
    if (c == ' ') return cur - sentence;
    ++cur;
  }
}

int main(int argc, const char *argv[]) {
  printf("%d\n", first_word_length(argv[1]));
  return 0;
}

It may differ depending on your current system and compiler, but on my x64 linux system with clang version 14, I can reproduce the error

$ clang++ main.cc 
main.cc:9:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
1 warning generated.

$ ./a.out "hello world"
5

$ ./a.out "hello"
Illegal instruction (core dumped)

On the other hand, gcc seems to return 0

$ g++ main.cc
main.cc: In function 'int first_word_length(const char*)':
main.cc:9:1: warning: control reaches end of non-void function [-Wreturn-type]
    9 | }
      | ^

$ ./a.out "hello world"
5

$ ./a.out "hello"
0

At this point, I am actually not sure which of gcc or clang/llvm way of handling this is more appropriate. On one hand, gcc is preventing system crash, albeit synthesizing a faux return value, while clang/llvm is abruptly crashing the program, alerting the developer. Probably the better way is to raise this as an error rather than warning.

Now, I turn on -Wall -Wextra -pedantic flags by default.