Both sides previous revision
Previous revision
Next revision
|
Previous revision
|
programming:debug [2008/10/30 09:20] cyril |
programming:debug [2013/09/19 16:41] (current) |
====== Debugging ====== | ====== Debugging ====== |
==== Colorgcc ==== | |
| |
- install colorgcc | If you look directly at gcc output, you should install [[software:colorgcc|ColorGCC]] which displays errors in red and warning in yellow. |
- make sure ~/bin path is in your $PATH variable before /usr/bin | |
- place symlinks in ~/bin/:<code> | |
cc -> /usr/bin/colorgcc | |
g++ -> /usr/bin/colorgcc | |
gcc -> /usr/bin/colorgcc | |
</code> | |
- create a ~/.colorgccrc file, and define inside the location of the real cc, gcc, g++ binaries:<code> | |
/usr/bin/cc, gcc, g++ | |
</code> | |
| |
Source: [[http://en.opensuse.org/Libzypp/Devel/colorgcc]] | |
| |
==== Segmentation Faults ==== | ===== Segmentation Faults ===== |
=== The crash occurs where the error is === | ==== The crash occurs where the error is ==== |
| |
It's the simpler case, which fortunately happens (null pointers, etc). | It's the simpler case, which fortunately happens (null pointers, etc). |
| |
The solution is to use a debugger like GDB to watch variable contents (see [[#gdb_summary]]). | The solution is to use a debugger like [[software:gdb|GDB]] to watch variable contents. |
| |
You have several possibilities to get into the program where the segfault occurred : | You have several possibilities to get into the program where the segfault occurred : |
* configure your shell to create a core dump when the program crashes (''ulimit -c unlimited'' for bash and zsh, ''limit coredumpsize unlimited'' for tcsh; the ''file'' command tells you which program created the core dump), and inspect the core dump with gdb. | * run the program with [[software:gdb|GDB]] |
| * configure your shell to create a core dump when the program crashes (''ulimit -c unlimited'' for bash and zsh, ''limit coredumpsize unlimited'' for tcsh; the ''file'' command tells you which program created the core dump), and inspect the core dump with [[software:gdb|GDB]]. |
* [[howtos-tips#catching_signals|catch the sigsegv signal]] and freeze the program, then attach the debugger to the running program. | * [[howtos-tips#catching_signals|catch the sigsegv signal]] and freeze the program, then attach the debugger to the running program. |
| |
=== The crash does not occur directly === | ==== The crash does not occur directly ==== |
| |
Then you have to use a memory checker, such as ''valgrind''. The ''memcheck'' tool will tell you about all memory access errors even if they don't throw segfault. | Then you have to use a memory checker, such as [[software:valgrind|Valgrind]]. The ''memcheck'' tool will tell you about all memory access errors even if they don't throw segfault. |
| |
<code bash> | <code bash> |
valgrind --tool=memcheck <your-program> <args> | valgrind --tool=memcheck <your-program> <args> |
valgrind <your-program> <args> | valgrind <your-program> <args> # memcheck is the default tool |
</code> | </code> |
| |
| ===== Memory leaks ===== |
| |
==== GDB Summary ==== | The solution is again [[software:valgrind|Valgrind]]: |
| <code bash> |
| valgrind --leak-check=full <program> <args> |
| </code> |
| |
== Starting == | |
* **# ''gdb <exec-file>''** | |
* **# ''gdb <exec-file> <core-file>''** : inspect the core dump | |
* **# ''gdb <exec-file> <pid>''** : attach to the running process | |
| |
== Running == | |
* **''run <program-parameters...>''** (short "r") : start the program | |
* **''step [count]''** (short "s") : step one line | |
* **''stepi [count]''** (short "si") : step one instruction | |
* **''next [count]''** (short "n") : step one line without entering in functions | |
* **''continue''** (short "c") : continue the program | |
* **''finish''** (short "fin") : execute until selected stack frame returns | |
* **''advance [source-file]:<line>''** (short "adv") : continue up to the given location | |
* **''call <func-name>''** (short "ca") : call a function (the context is copied so that it is not modified) | |
* **''kill''** (short "k") : stop the program | |
| |
== Navigating == | ===== Errors prevention ===== |
* **''backtrace''** (short "bt") : show the stack | |
* **''frame <frame-number>''** (short "f") : move to the stack drame number | |
* **''list [source-file]:<line|function>''** (short "l") : show source code | |
| |
== Threads == | |
* **''thread <thread-num>''** (short "t") : switch to thread | |
* **''info threads''** (short "i th") : show list of current threads | |
| |
== Breakpoints == | |
* **''break [source-file]:<line|function> [thread <thread-num>] [if <condition>]''** (short "b") : set a breakpoint | |
* **''info breakpoints''** (short "i b") : show all current breakpoints | |
* **''condition <breakpoint-number> <condition>''** (short "cond") : specify the breakpoint to break only if condition is true | |
* **''delete breakpoints <breakpoint-number>''** (short "del b", "del") : delete a breakpoint | |
* **''enable/disable <breakpoint-numbers...>''** (short "en" and "dis") : enable or disable some breakpoints | |
| |
== Inspecting data == | |
* **''print <var-name>''** (short "p") : print the value/content of the variable | |
* **''print *<pointer>@<nelements>''** : print nelements of the array | |
* **''print/<format> <var-name>''** : print with a certain format (x for hexa, ...) | |
* **''display <var-name>''** (short "disp") : display the value/content of the variable at every step | |
* **''awatch <var-name>''** (short "aw") : stops the execution whenever the variable is read or written | |
* **''watch <cond-on-var>''** (short "wa") : stops the execution whenever the condition on the variable becomes true | |
* **''ptype <var-name>''** : type of variable | |
* **''x <addr>''** : print the content of memory, can format with /<format> too | |
* **''set variable <var-name> = <value>''** : change variable value | |
| |
== Files == | |
| |
* **''source <file-name>''** : load a set of commands from a file | |
* You can define macros in ~/.gdbinit | |
| |
==== Errors prevention ==== | |
| |
It is interesting to know the sooner possible about problems. You should then use the ''assert()'' macro to check all of your parameters or variables that could cause a crash or an error. When debug is not enabled, there will be no code produced and thus no overhead. | It is interesting to know the sooner possible about problems. You should then use the ''assert()'' macro to check all of your parameters or variables that could cause a crash or an error. When debug is not enabled, there will be no code produced and thus no overhead. |
If you don't want to save core dumps, you can still [[howtos-tips#catching_signals|catch the sigabrt signal]], freeze the program and attach a debugger. You can even unfreeze the program with the debugger (eg by changing a variable content), and continue the program to see what happens. | If you don't want to save core dumps, you can still [[howtos-tips#catching_signals|catch the sigabrt signal]], freeze the program and attach a debugger. You can even unfreeze the program with the debugger (eg by changing a variable content), and continue the program to see what happens. |
| |
==== System calls ==== | ===== System calls ===== |
| |
''strace'' prints a list of system calls made by the program. | ''strace'' prints a list of system calls made by the program. |
| |
| |
| ======= Classic compilation errors ======= |
====== Classic compilation errors ====== | |
| |
Or not so classic... | Or not so classic... |