Подтвердить что ты не робот

Как получить выход gdb, если программа преуспевает, сломается, если программа выйдет из строя?

Кажется, у меня в моем коде есть какая-то многопоточная ошибка, из-за которой он падает каждый раз через 30 запусков своего тестового набора. Набор тестов не является интерактивным. Я хочу запустить свой тестовый пакет в gdb и нормально выйти из gdb, если программа выйдет из строя или перерыв (и показать приглашение отладки), если он сработает. Таким образом, я могу позволить тестовому набору многократно запускать, забирать чашку кофе, возвращаться и получать отличное отладочное приглашение. Как это сделать с помощью gdb?

4b9b3361

Ответ 1

Это немного глупо, но вы могли бы сделать:

gdb -ex='set confirm on' -ex=run -ex=quit --args ./a.out

Если a.out завершится нормально, он просто выведет вас из 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;
}

Ответ 2

Самый простой способ - использовать 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, для регистрации обработчика события из командной строки или с помощью файла .gdbinit.

Ответ 3

Вы также можете запустить обратную трассировку, когда программа выйдет из строя и выйдет из gdb с кодом возврата дочернего процесса:

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

Ответ 4

Создайте файл с именем .gdbinit и он будет использоваться при запуске gdb.

run
quit

Запуск без параметров:

gdb --args prog arg1...

Вы говорите gdb для запуска и выхода, но он должен прекратить обработку файла, если произошла ошибка.

Ответ 5

Заставьте сбрасывать ядро ​​при его сбое. Если вы используете linux, прочитайте man-страницу man core, а также встроенную ulimit, если вы используете bash.

Таким образом, когда он выйдет из строя, вы найдете хороший файл ядра, который вы можете передать в gdb:

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

Ответ 6

Если вы поместите следующие строки в свой ~/.gdbinit файл, gdb выйдет, когда ваша программа выйдет с кодом состояния 0.

python

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

gdb .events .exited .connect ( exit_handler )

end

Вышеизложенное является уточнением ответа Кевина.

Ответ 7

Вы не получаете основной файл, когда он падает? Начните gdb, как это "gdb -c core", и выполните трассировку стека.

Скорее всего, вы захотите использовать Valgrind.