2011-12-28 20 views
13

Wydaje mi się, że mam pewien błąd wielowątkowości w moim kodzie, który powoduje awarię co 30 uruchomień pakietu testowego. Zestaw testów nie jest interaktywny. Chcę uruchomić mój pakiet testowy w gdb i normalnie wyjść z gdb, jeśli program wyjdzie normalnie, lub przerwać (i wyświetlić monit o usunięcie błędu), jeśli ulegnie awarii. W ten sposób mogę pozwolić zestawowi testowemu działać wielokrotnie, chodzić po filiżankę kawy, wracać i być przedstawiany z miłym monitorem debugowania. Jak mogę to zrobić z gdb?Jak uzyskać wyjście gdb, jeśli program się powiedzie, przerwać w razie awarii programu?

Odpowiedz

18

Jest trochę hacky, ale można zrobić:

gdb --eval-command=run --eval-command=quit --args ./a.out 

przypadku. out kończy się normalnie, to po prostu wyrzuci cię z GDB. Ale jeśli awarii, program nadal będzie aktywny, więc GDB zazwyczaj zapyta, czy na pewno chcesz zrezygnować z aktywnym gorszy:

Program received signal SIGABRT, Aborted. 
0x00007ffff72dad05 in raise (sig=...) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. 
    in ../nptl/sysdeps/unix/sysv/linux/raise.c 
A debugging session is active. 

    Inferior 1 [process 15126] will be killed. 

Quit anyway? (y or n) 

Tak jak mówiłem, nie całkiem, ale to działa, dopóki nie zrezygnowałem z podpowiedzi, aby wyjść z aktywnym procesem. Prawdopodobnie istnieje również sposób użycia polecenia gdb: quit: pobiera on argument numeryczny, który jest kodem wyjścia dla sesji debugowania. Być może więc możesz użyć --eval-command = "quit stuff", gdzie coś jest pewnym wyrażeniem GDB, które odzwierciedla, czy gorszy działa, czy nie.

+0

Jestem na OS X Snow Leopard, a gdb tutaj nie obsługuje --eval-command, ale i tak wybiorę twoją odpowiedź. – Hongli

+0

try gdb --command = <(echo run) --command = <(echo quit) – acm

+0

Myślę, że to nie zadziała, jeśli masz 'set confirm off' w twoim pliku' .gdbinit', GDB będzie zawsze return ... – Kevin

3

Zrób rdzeń podczas awarii. Jeśli korzystasz z systemu Linux, przeczytaj stronę podręcznika man man core, a także wbudowaną wersję ulimit, jeśli używasz bash.

W ten sposób, gdy się zawiesi znajdziesz miłą corefile że można karmić do gdb:

$ ulimit -c unlimited 
$ ... run program ..., gopher coffee (or reddit ;) 
$ gdb progname corefile 
0

Nie dostajesz pliku core, gdy się zawiesza? Uruchom gdb jak ten "gdb -c core" i wykonaj traceback stosu.

Prawdopodobnie będziesz chciał używać Valgrind.

6

Najprostszym sposobem jest użycie Python API oferowane przez gdb:

def exit_handler(event): 
    gdb.execute("quit") 

gdb.events.exited.connect(exit_handler) 

Można nawet zrobić to z jednej linii:

(gdb) gdb.events.exited.connect(lambda x : gdb.execute("quit") 

Można również zbadać kod zwrotny, aby zapewnić, że to "normalny" kod, którego oczekiwałeś z event.exit_code.

Można go używać w połączeniu z --eval-command lub --command jak wspomniano przez @acm zarejestrować obsługi zdarzeń z wiersza polecenia lub z pliku .gdbinit.

3

Można również wywołać ślad po awarii programu i niech zjazd gdb z kodem powrotu procesu potomnego:

gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg 
+3

To nie jest najlepsza odpowiedź na to pytanie, ale pomogło mi to w odpowiedzi na moje pytanie! Dziękuję, nie wiedziałeś o "powrocie-dziecko-wynik" –

1

Utwórz plik o nazwie .gdbinit i będzie on używany podczas gdb jest uruchomiona.

run 
quit 

Run bez opcji:

gdb --args prog arg1... 

Mówisz gdb uruchomić i zamknąć, ale powinien zatrzymać przetwarzania pliku w przypadku wystąpienia błędu.

0

Jeśli umieścisz następujące linie w pliku ~/.gdbinit, gdb wyjdzie gdy program kończy pracę z kodem stanu 0.

python 

def exit_handler (event): 
    if event .exit_code == 0: 
    gdb .execute ("quit") 

gdb .events .exited .connect (exit_handler) 

end 

Powyższe jest udoskonalenie odpowiedź Kevina.

Powiązane problemy