Skip to content
Advertisement

How to squash bug that only occurs with optimizations enabled

I’m in a bit of a pickle. I have some code that until recently ran fine but has now started to fail when optimizations are enabled. This code runs just fine with optimizations disabled -O0 both -O1 and -O2 cause the issue to occur (I don’t use -O3).

Unfortunately, I can’t post the source code (it’s rather involved and proprietary) but I’m going to attempt a minimal working example. Meanwhile I’d love to hear from anyone with experience what manner of C++ is even capable of resulting in something unexpected with optimizations enabled (what are the gotchas? what should I review first?).

Here’s something to at least give you the general idea of the code where I first found the issue:

struct Slice {
  const char* m_Data;
  size_t m_Size;
}
char scratch[1024];
Slice result;
Read(read, &result, scratch);
// with optimizations disabled, result contains 40 bytes of data with optimizations enabled m_Size is suddenly zero!?

This is really nothing fancy, this is simple and straightforward C++.

I’m using gcc-4.8.1 but I have the same issue with clang++ on OS X (Visual C++ on Windows does not appear to have this issue).

Advertisement

Answer

Usually such an unstable behaviour (different results with different optimization options, or different results under different compilers, or even different results on different runs) happen due to undefined behavior, and most often due to some memory management problems (uninitialized value use, bad pointer management, etc.)

There are special tools to identify some (though not all) such problems.

One of them is valgrind, you just build your program and call valgrind ./program. It will track many of memory access problems, uninitialized values, etc. Though it decreases performance substantially.

Another is address sanitizing option of compilers. For gcc, you build your program with -fsanitize=address, and then run program normally. For other compilers there may be similar options. It catches a bit different set of problems than valgrind, and does not have much perfomance problems.

In both cases, you can build the program with any optimization option. The problem will most probably show up anyway. Some false positives may show up, but this might depend on your code.

Another set of tools are static code analyzers such as cppcheck.

Of course, as usual, you can try debugging the program or adding debug output etc, but this might be not that effective, because any change to a program can make behavior back to normal.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement