Как выйти из gdb, если программа преуспевает, сломать, если программа аварийно завершает работу?
У меня, кажется, есть какая-то ошибка многопоточности в моем коде, которая заставляет его сбой один раз каждые 30 запусков его тестового набора. Набор тестов не является интерактивным. Я хочу запустить свой набор тестов в gdb и выйти из gdb нормально, если программа выходит нормально, или сломать (и показать приглашение отладки), если он аварийно завершает работу. Таким образом, я могу позволить тестовому набору работать несколько раз, выпить чашечку кофе, вернуться и получить хороший запрос на отладку. Как я могу сделать это с gdb?
7 ответов
Это немного hacky, но вы могли бы сделать:
gdb -ex='set confirm on' -ex=run -ex=quit --args ./a.out
если a.выход завершается нормально, он просто выпадет из GDB. Но если вы потерпите крах, программа все равно будет активна, поэтому GDB обычно предложит, если вы действительно хотите выйти с активным подчиненным:
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)
как я уже сказал, не очень, но это работает, пока вы не отключили приглашение выйти с активным процессом. Вероятно, есть способ использовать gdb quit
команда тоже: требуется числовое аргумент, который является кодом выхода для сеанса отладки. Поэтому, возможно, вы можете использовать --eval-command= "quit stuff", где stuff-это некоторое выражение GDB, которое отражает, работает ли подчиненный или нет.
эта программа может быть использована для тестирования:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
if (time(NULL) % 2) {
raise(SIGINT);
}
puts("no crash");
return EXIT_SUCCESS;
}
самый простой способ-использовать Python API предложил gdb
:
def exit_handler(event):
gdb.execute("quit")
gdb.events.exited.connect(exit_handler)
вы даже можете сделать это с помощью одной строки:
(gdb) gdb.events.exited.connect(lambda x : gdb.execute("quit")
вы также можете проверить код возврата, чтобы убедиться, что это" нормальный " код, который вы ожидали с event.exit_code
.
вы можете использовать его в связке с --eval-command
или --command
как упоминалось @acm для регистрации обработчика событий из командной строки или с помощью .
вы также можете запустить backtrace при сбое программы и позволить gdb выйти с кодом возврата дочернего процесса:
gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg
сделать его дамп ядра, когда он падает. Если вы на linux, прочитайте man core
man-страница, а также ulimit
builtin, если вы работаете bash
.
таким образом, когда он падает, вы найдете хороший corefile, который вы можете подать в gdb:
$ ulimit -c unlimited
$ ... run program ..., gopher coffee (or reddit ;)
$ gdb progname corefile
создайте файл с именем .gdbinit
и он будет использоваться при запуске gdb.
run
quit
запуск без опций:
gdb --args prog arg1...
вы говорите gdb для запуска и выхода, но он должен прекратить обработку файла, если произойдет ошибка.
Если вы поместите следующие строки в ваш , gdb
выйдет, когда ваша программа завершается с кодом состояния 0.
python
def exit_handler ( event ):
if event .exit_code == 0:
gdb .execute ( "quit" )
gdb .events .exited .connect ( exit_handler )
end
выше читайте ответ Кевина.
вы не получаете основной файл, когда он падает? Запустите gdb как это "ядро gdb-c" и выполните трассировку стека.
скорее всего, вы захотите использовать Valgrind.