Debugging Optimized Code
Debugging C/C++ works best with the code that has not been optimized. Turning on even the minimal optimization level (-O1) can introduce various debugging glitches:
- Breakpoints not setting in some locations
- Stepping through functions could appear sporadic, jumping up and down
- Some variable values could be completely missing
To avoid this, C/C++ projects usually come with two configurations: Debug with optimization disabled (-O0) and Release with optimizations enabled (-O3 or –Os).
If this layout does not work due to some reason, you can try the workarounds described below.
Updating GCC version
Newer versions of GCC and GDB tend to handle it slightly better, so updating it could help. It will still be far from perfect though.
Selectively disabling optimization for individual files
If you are using MSBuild, you can override the optimization level of individual files by opening MSBuild project properties for the particular files, and changing the optimization level:For CMake projects, you can also use the file-level properties, or edit CMakeLists.txt directly:
set_source_files_properties(source.cpp PROPERTIES COMPILE_FLAGS -O0)
Note that unlike MSBuild, where the per-file setting would override the per-project one, CMake would simply add different optimization flags one after another. According to the GCC documentation, the last flag in the command line will then take effect:
If you use multiple -O options, with or without level numbers, the last such option is the one that is effective.
You can double-check it by adding an #error directive in the source file and building it. If you are using Ninja, it will output the command line used to build the failing file, so you can double-check which optimization option comes last:
Selectively disabling optimization for individual functions
Regardless of the build system used, you can de-optimize individual functions using the optimize attribute:
int __attribute__((optimize("O0"))) sum(int x, int y) { return x + y; }
This can be defined conditionally to only affect the Debug configuration:
#ifdef DEBUG #define UNOPTIMIZED __attribute__((optimize("O0"))) #else #define UNOPTIMIZED #endif int UNOPTIMIZED sum(int x, int y) { return x + y; }
You can also use the #pragma GCC optimize directive to change the optimization level of all functions within a given block:
#pragma GCC push_options #pragma GCC optimize ("O0") int sum(int x, int y) { return x + y; } #pragma GCC pop_options
Other tricks
If you only care about viewing specific variable values, you can try declaring them as volatile. This would disable most optimizations for a particular variable, also making it visible in the debugger. Similarly for functions, you can try using __attribute__((noinline)) to prevent inlining of a particular function.