Как заставить GDB завершиться, если программа завершится успешно, прерваться, если программа потерпит крах? - PullRequest
18 голосов
/ 28 декабря 2011

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

Ответы [ 7 ]

21 голосов
/ 28 декабря 2011

Это немного хакерски, но вы могли бы сделать:

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;
}
8 голосов
/ 01 января 2012

Самый простой способ - использовать 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.

4 голосов
/ 23 октября 2012

Вы также можете вызвать возврат в случае сбоя программы и позволить GDB завершиться с кодом возврата дочернего процесса:

gdb -return-child-result -ex run -ex "thread apply all bt" -ex "quit" --args myProgram -myProgramArg
3 голосов
/ 17 июля 2013

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

run
quit

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

gdb --args prog arg1...

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

2 голосов
/ 28 декабря 2011

Сделать это дамп ядра при сбое.Если вы работаете в Linux, прочитайте справочную страницу man core, а также встроенную ulimit, если вы используете bash.

. Таким образом, в случае сбоя вы найдете хороший файл core, который выМожно кормить на GDB:

$ ulimit -c unlimited
$ ... run program ..., gopher coffee (or reddit ;)
$ gdb progname corefile
1 голос
/ 16 сентября 2017

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

python

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

gdb .events .exited .connect ( exit_handler )

end

Выше приведено уточнение ответа Кевина.

0 голосов
/ 28 декабря 2011

Вы не получаете файл ядра, когда он падает? Запустите GDB, как это «ядро GDB-C» и выполните трассировку стека.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...