Development/Tutorials/Debugging/Debugging symbols
Debugging symbols allow you to debug your application better. Debugging symbols are added to your binary by the compiler. You have to decide during the cmake step if you want debugging symbols or not. To compile your application with debugging symbols, use
cmake . -DCMAKE_BUILD_TYPE=debugfull
to compile it without debugging symbols, use
cmake . -DCMAKE_BUILD_TYPE=release
Depending on your decision, output generated with the command kDebug will also be (debugfull) or not be (release) added to your application.
As an example, let's write an application that crashes:
main.cpp
#include <KApplication> #include <KAboutData> #include <KCmdLineArgs> #include <KMessageBox> #include <iostream> using namespace std; int main (int argc, char *argv[]) { KAboutData aboutData( "tutorial1", 0, ki18n("Tutorial 1"), "1.0", ki18n("Displays a KMessageBox popup"), KAboutData::License_GPL, ki18n("(c) 2009"), ki18n("Some text..."), "http://tutorial.com/", "[email protected]"); KCmdLineArgs::init( argc, argv, &aboutData ); KApplication app; KMessageBox::questionYesNo( 0, i18n( "Hello World" ) ); int* i; cout << "i is at " << i << " value " << *i << endl; i=(int*)0x0; cout << "i is at " << i << " value " << *i << endl; return 0; }
CMakeLists.txt
project (tutorial1) find_package(KDE4 REQUIRED) include (KDE4Defaults) include_directories(${KDE4_INCLUDES}) set(tutorial1_SRCS main.cpp) kde4_add_executable(tutorial1 ${tutorial1_SRCS}) target_link_libraries(tutorial1 ${KDE4_KDEUI_LIBS}) install(TARGETS tutorial1 ${INSTALL_TARGETS_DEFAULT_ARGS})
Now let's compile this without debugging symbols:
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
We see that the resulting file is small:
# ll tutorial1 -rwxr-xr-x 1 root root 18879 Jul 11 18:07 tutorial1
With debugging symbols, the file is bigger:
cmake . -DCMAKE_BUILD_TYPE=debugfull && make # ll tutorial1 -rwxr-xr-x 1 root root 256622 Jul 11 18:09 tutorial1
Backtraces
Now let's start the application and look at the backtrace:
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
Gives you the backtrace
Application: Tutorial 1 (tutorial1), signal SIGSEGV �[?1034h[Thread debugging using libthread_db enabled] 0x00007f58abba4cb0 in nanosleep () from /lib64/libc.so.6 [Current thread is 1 (Thread 0x7f58b0cfd750 (LWP 21264))] Thread 1 (Thread 0x7f58b0cfd750 (LWP 21264)): [KCrash Handler] #5 0x00000000004016aa in main ()
The debugging build
cmake . -DCMAKE_BUILD_TYPE=debugfull && make -j4
Gives you the backtrace
Application: Tutorial 1 (tutorial1), signal SIGSEGV �[?1034h[Thread debugging using libthread_db enabled] 0x00007fd0b8161cb0 in nanosleep () from /lib64/libc.so.6 [Current thread is 1 (Thread 0x7fd0bd2ba750 (LWP 21327))] Thread 1 (Thread 0x7fd0bd2ba750 (LWP 21327)): [KCrash Handler] #5 0x0000000000401625 in main (argc=1, argv=0x7fffc52f5138) at /root/kdehello/main.cpp:25
So you see: with debugging symbols, you see the line number where the crash occurred. Without, you do not see this.
Where are they?
Where are the debugging symbols stored? Use objdump -g to find out:
# objdump -g tutorial1-release | wc -l 511 # objdump -g tutorial1-debugfull | wc -l 40943
It is important to know that the code lines (in assembler) to be executed actually do not differ a lot. We see this when disassembling the code:
# objdump -d tutorial1-debugfull | wc -l 658 # objdump -d tutorial1-release | wc -l 697