GDB: Automatisch 'Weiter' Ing?

Auf die schnelle dieser Zeit.

Ist es möglich (anders als die EINGABETASTE drücken forever) für gdb ständig next durch ein Programm Zeile für Zeile zu finden, wo ein Fehler passiert ist?

Bearbeiten: continue ist nicht das, was ich möchte; ich möchte sehen, wie effektiv die komplette Ausführung des Programms, Zeile für Zeile, als würde man aus nexting über und über.

  • Ausgewählte Antwort
    Michael Burr
    28. April 2011

    Hier ist etwas, das ist so ein hack, ich bin ein bisschen peinlich, um es zu veröffentlichen. Aber wenn Sie benötigen nur eine einmalige, könnte es tun, gut genug, um zu lassen Sie erhalten die Informationen, die Sie wollen. Es sollte wirklich einen besseren Weg.

    Definieren Sie ein wenig dumm gdb-Skript ausführen der step oder next - Befehl eine bestimmte Anzahl von Zeiten:

    # file: step_mult.gdb
    
    define step_mult
        set $step_mult_max = 1000
        if $argc >= 1
            set $step_mult_max = $arg0
        end
    
        set $step_mult_count = 0
        while ($step_mult_count < $step_mult_max)
            set $step_mult_count = $step_mult_count + 1
            printf "step #%d\n", $step_mult_count
            step
        end
    end
    

    (Ich habe Schritt statt next für keinen besonders guten Grund; nur, es zu ändern, was auch immer Sie brauchen.)

    Dann können Sie ausführen dieses Befehls (mit einem optionalen zählen), und es erscheint jedes step oder next schön.

    Hier ist ein Beispielprogramm, das werde Abstürzen, wenn er versucht zu dereferenzieren eines NULL-Zeigers:

    #include<stdio.h>
    
    int x[] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8,9, 10 
    };
    
    int* p[11];
    
    int main()
    {
        int i;
    
        for (i = 0; i < 11; ++i) {
            p[i] = &x[i];
        }
    
        p[5] = 0;
    
        for (i = 0; i < 11; ++i) {
            printf( "*p[%d] == %d\n", i, *p[i]);
        }
    
        return 0;
    }
    

    Hier ist ein gdb-Sitzung (auf Windows) Debuggen, Programmieren und mithilfe des step_mult script:

    C:\temp>gdb test.exe
    GNU gdb (GDB) 7.2
    ...
    Reading symbols from C:\temp/test.exe...done.
    
    (gdb) source c:/temp/step_mult.gdb
    (gdb) start
    
    Temporary breakpoint 1 at 0x401385: file C:\temp\test.c, line 23.
    Starting program: C:\temp/test.exe
    [New Thread 5396.0x1638]
    
    Temporary breakpoint 1, main () at C:\temp\test.c:23
    23          for (i = 0; i < 11; ++i) {
    
    (gdb) step_mult 70
    
    step #1
    24              p[i] = &x[i];
    step #2
    23          for (i = 0; i < 11; ++i) {
    step #3
    24              p[i] = &x[i];
    step #4
    23          for (i = 0; i < 11; ++i) {
    step #5
    24              p[i] = &x[i];
    step #6
    23          for (i = 0; i < 11; ++i) {
    step #7
    24              p[i] = &x[i];
    step #8
    23          for (i = 0; i < 11; ++i) {
    step #9
    24              p[i] = &x[i];
    step #10
    23          for (i = 0; i < 11; ++i) {
    step #11
    24              p[i] = &x[i];
    step #12
    23          for (i = 0; i < 11; ++i) {
    step #13
    24              p[i] = &x[i];
    step #14
    23          for (i = 0; i < 11; ++i) {
    step #15
    24              p[i] = &x[i];
    step #16
    23          for (i = 0; i < 11; ++i) {
    step #17
    24              p[i] = &x[i];
    step #18
    23          for (i = 0; i < 11; ++i) {
    step #19
    24              p[i] = &x[i];
    step #20
    23          for (i = 0; i < 11; ++i) {
    step #21
    24              p[i] = &x[i];
    step #22
    23          for (i = 0; i < 11; ++i) {
    step #23
    27          p[5] = 0;
    step #24
    29          for (i = 0; i < 11; ++i) {
    step #25
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #26
    *p[0] == 0
    29          for (i = 0; i < 11; ++i) {
    step #27
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #28
    *p[1] == 1
    29          for (i = 0; i < 11; ++i) {
    step #29
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #30
    *p[2] == 2
    29          for (i = 0; i < 11; ++i) {
    step #31
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #32
    *p[3] == 3
    29          for (i = 0; i < 11; ++i) {
    step #33
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #34
    *p[4] == 4
    29          for (i = 0; i < 11; ++i) {
    step #35
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #36
    
    Program received signal SIGSEGV, Segmentation fault.
    0x004013d2 in main () at C:\temp\test.c:30
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #37
    
    Program received signal SIGSEGV, Segmentation fault.
    0x004013d2 in main () at C:\temp\test.c:30
    30              printf( "*p[%d] == %d\n", i, *p[i]);
    step #38
    
    Program exited with code 030000000005.
    step #39
    The program is not being run.
    (gdb)
    

    Leider, da das Skript nicht beenden, wenn der segfault passiert, gdb entscheidet einfach Debuggen beenden Sie das Programm, so können Sie keine weitere sinnvolle Untersuchungen. Aber das Protokoll kann immer noch nützlich sein.

    Ich bin sicher, es gibt zahlreiche Möglichkeiten, man könnte das Skript intelligenter. Leider habe ich keine Idee, wie das zu tun, und der Benutzer-Ebene docs für GDB, scheinen nicht allzu hilfreich für diese details. Am besten wäre es, wenn das script erkennen könnte der segfault oder signal passiert hatte und nur halt dann, anstatt sich auf einige beliebige Anzahl. Ich Stelle mir die gdb/MI-Schnittstelle, oder wohl auch das Python-scripting-Schnittstelle kann ein guter Mechanismus, aber ich weiß nichts über diese.

    Nach Ihrem ersten Lauf konnte Sie mit der count angezeigt (37 in meinem Beispiel) und starten Sie das Programm und geben Sie eine Zahl, die ist nur schüchtern von wo Sie stürzte vor, und kontrollieren Sie Sie manuell.

    Wie ich schon sagte, es ist nicht besonders schön - aber vielleicht bekommen Sie es.

4 Antworten