GDB

From Alliance Doc
Revision as of 14:49, 10 December 2018 by Diane27 (talk | contribs) (Created page with "Ensuite, il est possible d'attacher le débogueur directement. {{Command|gdb attach 12691 }}")
Jump to navigation Jump to search
Other languages:

GDB est un débogueur pour investiguer des problèmes présents dans les logiciels. GDB est un acronyme voulant dire GDB: The GNU Project Debugger

Description

Avec un débogueur, il est possible de trouver rapidement la cause d'un problème dans un logiciel. Le cas d'utilisation typique est pour trouver les erreurs de segmentation. Si vous désirez trouver un problème de mémoire (par exemple, une fuite de mémoire), il est conseillé d'utiliser Valgrind.

Cas d'utilisation

Trouver la cause d'une erreur de segmentation directement avec le débogueur

Dans cette section, le programme suivant est utilisé :

File : program.cpp

#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char**argv) {
	
	vector<int> numbers;

	int iterator = 1000;

	while(iterator --) {
		numbers.push_back(iterator);
	}

	cout << numbers[1000000] << endl;

	return 0;
}


Ce programme génère une erreur de segmentation lorsqu'on l'exécute.

[name@server ~]$ g++ -g program.cpp  -o program
[name@server ~]$ ./program
Segmentation fault (core dumped)
[name@server ~]$


On peut alors l'exécuter à l'intérieur du débogueur. Notez que l'on a compilé avec l'option -g pour permettre au débogueur de décoder les symboles et fournir davantage d'information sur la source du bogue. On exécute l'application à l'intérieur du débogueur comme suit :

Question.png
[name@server ~]$ gdb ./program
(gdb) run
Starting program: /home/seb/program ./program

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400c17 in main (argc=2, argv=0x7fffffffda88) at program.cpp:15
15		cout << numbers[1000000] << endl;
Missing separate debuginfos, use: debuginfo-install glibc-2.16-31.fc18.x86_64 libgcc-4.7.2-8.fc18.x86_64 libstdc++-4.7.2-8.fc18.x86_64

(gdb) bt
#0  0x0000000000400c17 in main (argc=2, argv=0x7fffffffda88) at program.cpp:15

Ici, l'erreur est causée par la ligne 15. Le code accède à l'indice 1000000, mais le tableau contient seulement 1000 éléments.

Trouver la cause d'une erreur de segmentation avec un fichier core

Dans cet exemple, on utilise le programme de la section précédente, mais sans utiliser le débogueur directement. Ceci est utile pour un bogue qui se produit longtemps après le début de l'exécution du programme.

Afin de trouver la cause de l'erreur de segmentation, il faut générer un fichier core. Pour ce faire, il faut activer la création de tels fichiers.

Question.png
[name@server ~]$ ulimit -c unlimited

En exécutant à nouveau le même programme, un fichier core sera écrit.

[name@server ~]$ ./program
Segmentation fault (core dumped)
[name@server ~]$ file core.18158
core.18158: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './program'
[name@server ~]$


En utilisant l'exécutable programme et le fichier core, il est possible de tracer l'exécution jusqu'à l'erreur.

Question.png
[name@server ~]$ gdb -q ./program 
Reading symbols from /home/seb/program...done.

(gdb) core-file core.18246
[New LWP 18246]
Core was generated by `./program'.
Program terminated with signal 11, Segmentation fault.
#0  0x0000000000400c17 in main (argc=1, argv=0x7fff2315c848) at
program.cpp:15
15              cout << numbers[1000000] << endl;
Missing separate debuginfos, use: debuginfo-install
glibc-2.16-31.fc18.x86_64 libgcc-4.7.2-8.fc18.x86_64
libstdc++-4.7.2-8.fc18.x86_64

(gdb) bt
#0  0x0000000000400c17 in main (argc=1, argv=0x7fff2315c848) at
program.cpp:15

On obtient alors le même résultat qu'en ayant exécuté le code à l'intérieur du débogueur.

Attacher le débogueur à un processus existant

Il est possible de déboguer un processus existant, par exemple une tâche qui s'exécute sur un nœud de calcul. Pour ce faire, il faut d'abord trouver le numéro du processus.

Question.png
[name@server ~]$ ps aux | grep firefox | grep -v grep
seb      12691  6.4  7.5 1539672 282656 ?      Sl   08:53   6:48 /usr/lib64/firefox/firefox http://www.google.ca/

Ensuite, il est possible d'attacher le débogueur directement.

Question.png
[name@server ~]$ gdb attach 12691

After having done this, a lot of information is displayed.

There are many commands available within GDB. One of the most useful is backtrace, or bt. This commands shows the current call stack.

 
 (gdb) bt
#0  0x00000033646e99ad in poll () from /lib64/libc.so.6
#1  0x0000003db86849f3 in PollWrapper(_GPollFD*, unsigned int, int) () from /usr/lib64/firefox/xulrunner/libxul.so
#2  0x0000003366e47d24 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#3  0x0000003366e47e44 in g_main_context_iteration () from /lib64/libglib-2.0.so.0
#4  0x0000003db86849a2 in nsAppShell::ProcessNextNativeEvent(bool) () from /usr/lib64/firefox/xulrunner/libxul.so
#5  0x0000003db869a7d1 in nsBaseAppShell::DoProcessNextNativeEvent(bool, unsigned int) () from /usr/lib64/firefox/xulrunner/libxul.so
#6  0x0000003db869a8ea in nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal*, bool, unsigned int) () from /usr/lib64/firefox/xulrunner/libxul.so
#7  0x0000003db89810c2 in nsThread::ProcessNextEvent(bool, bool*) () from /usr/lib64/firefox/xulrunner/libxul.so
#8  0x0000003db89563eb in NS_ProcessNextEvent(nsIThread*, bool) () from /usr/lib64/firefox/xulrunner/libxul.so
#9  0x0000003db873056f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) () from /usr/lib64/firefox/xulrunner/libxul.so
#10 0x0000003db89a4ab7 in MessageLoop::Run() () from /usr/lib64/firefox/xulrunner/libxul.so
#11 0x0000003db869a1b3 in nsBaseAppShell::Run() () from /usr/lib64/firefox/xulrunner/libxul.so
#12 0x0000003db857d92d in nsAppStartup::Run() () from /usr/lib64/firefox/xulrunner/libxul.so
#13 0x0000003db7d18f4a in XREMain::XRE_mainRun() () from /usr/lib64/firefox/xulrunner/libxul.so
#14 0x0000003db7d1b007 in XREMain::XRE_main(int, char**, nsXREAppData const*) () from /usr/lib64/firefox/xulrunner/libxul.so
#15 0x0000003db7d1b259 in XRE_main () from /usr/lib64/firefox/xulrunner/libxul.so
#16 0x0000000000402c23 in do_main(int, char**, nsIFile*) ()
#17 0x0000000000402403 in main ()
 (gdb) quit
A debugging session is active.

	Inferior 1 [process 12691] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/lib64/firefox/firefox, process 12691
 


Advanced usage

In the previous sections, we used the run and backtrace commands. Many more commands are available to debug in an interactive way, by stopping the program. For example, you can set breakpoints on functions or lines of code, or whenever a given variable is modified. When execution is interrupted, you can analyse the state of the program by printing the value of variables. The following table contains a list of the main commands.

Main GDB commands
Command Shortcut Argument Description
run/kill r/k - begin/stop execution
where / backtrace bt - displays the backtrace
break b src.c:line_number or function sets a break point at the given line of code or function
watch - variable name interrupts the program when a variable is modified
continue c - resume the program
step s - execute the next operation
print p variable name displays the content of a variable
list l src.c:number displays the given line of code

Displaying STL structures

By default, GDB does not display C++ STL structures very well. Many solutions are given here. The simplest solution is probably this one, which is to copy this file in your home folder, with the name ~/.gdbinit.

Other resources