2016-11-07 6 views
3

Ich habe versucht, GDB zu verwenden, um einen segfault in Code zu beheben, den ich schreibe. GDB zeigt keine Zeilennummern oder Funktionsnamen, wenn ich den Befehl backtrace verwende. Hier ist eine kurze Beispielprogramm, das mein Problem zeigt:Warum zeigt GDB keine Zeilennummern oder Funktionsnamen?

void segfault(int *b) { 
    // This causes a segfault on CentOS7 Intel 64-bit 
    b[-1] = 5; 
} 

void main() { 
    int a[10]; 
    segfault(a); 
} 

Jedoch, wenn ich mit

gcc -ggdb -O0 test.c -o segfaulttest 

kompilieren und verwenden gdb segfaulttest es zu laufen, wenn ich GDB verwenden Backtrace Befehl, den ich keine Zeilennummern erhalte oder Funktionsnamen. Ich würde erwarten, dass es main() und segfault() in der Spur auflisten.

Beispielausgabe

Reading symbols from /home/user/test/segfaulttest...done. 
(gdb) run 
Starting program: /home/user/test/segfaulttest 

Program received signal SIGSEGV, Segmentation fault. 
0x000000050040051c in ??() 
(gdb) bt 
#0 0x000000050040051c in ??() 
#1 0x0000000000000000 in ??() 
(gdb) 

ich benutze:

  • CentOS 7 (64 Bit)
  • GCC: gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
  • GDB ist gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

(Abgesehen : Ich habe das tatsächlich behoben Fehler in meinem Code, ich verstehe nur nicht, warum gdb backtrace mir nicht mehr Informationen zeigt).

Antwort

5

Sie haben den Teil des Stapels zerstört, der die Informationen enthält, die gdb wissen muss, wo sich Ihr Programm befindet.

0x000000050040051c in ??() 
    ^^^^^^^^ 

Dies ist die Nummer 5, die Ihr Code schrieb, ein 4 Byte int.

Wenn main() gestartet wird, wird die Rücksprungadresse auf dem Stapel gespeichert. Die Rückkehradresse ist wo main() zurückkommt, wenn es fertig ist. Dieser Ort ist eine Funktion, die Teil der Laufzeit ist, die main() aufgerufen hat.

Da diese Rücksprungadresse von Ihrem Code gestört/überschrieben wird, versucht die Ausführung, zu einer nicht vorhandenen Adresse zurückzuspringen, wodurch der Absturz verursacht wird.

Diese Adresse, 0x000000050040051c, ist jetzt das Programmzählerregister, das gespeichert wird, wenn das SIGSEGV-Signal an Ihren Prozess gesendet wird. gdb prüft diese Information, versucht herauszufinden, wo sich der Code befindet, der der Adresse 0x000000050040051c entspricht - welche nicht existiert.

+0

Danke für die schnelle, verständliche Antwort. Ich habe versucht, segfault() zu ändern: 'void segfault() {raise (SIGSEGV); } 'und rannte wieder gdb Ich konnte den StackTrace erfolgreich betrachten. –

Verwandte Themen