Программная установка точки останова в коде C или C ++ для gdb в Linux


105

Как я могу программно установить точку останова в коде C или C ++, которая будет работать для gdb в Linux?

Т.е.:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}

8
Очень второстепенное замечание (извините за придирки), но если вы беспокоитесь о переносимости, вы, вероятно, также беспокоитесь о правильности - следовательно, int mainа не void main.
Стюарт Голодец 01

@Stuart - Исправлено. Должен был сделать это некоторое время назад.
J. Polfer

4
@ J.Polfer: Это return 0не обязательно, это просто шум!
Lightness Races на орбите

Ответы:


107

Один из способов - сообщить о прерывании:

#include <csignal>

// Generate an interrupt
std::raise(SIGINT);

В C:

#include <signal.h>
raise(SIGINT);

ОБНОВЛЕНИЕ : MSDN заявляет, что Windows на самом деле не поддерживает SIGINT, поэтому, если переносимость вызывает беспокойство, вам, вероятно, лучше использовать SIGABRT.


Да, это должно работать во всех операционных системах / компиляторах / отладчиках.
Håvard S

1
Я не знаю других отладчиков, но GDB довольно гибок в обработке сигналов .
Cascabel

4
Мы обнаружили, что SIGTRAP лучше на некоторых
Unices

1
в Windows, MSVC вы можете использовать __debug_break, DebugBreak или _asm {int 3}.
Фернандо Гонсалес Санчес

2
@FernandoGonzalezSanchez: на самом деле имя функции, __debugbreak()а НЕ __debug_break() , как вы можете видеть здесь
Morix Dev

27

В проекте, над которым я работаю, мы делаем следующее:

raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */

(В нашем случае мы хотели резко вывести из строя, если это произошло вне отладчика, создавая, если возможно, отчет о сбое. Это одна из причин, по которой мы использовали SIGABRT. Чтобы сделать это переносимо на Windows, Mac и Linux, потребовалось несколько попыток. В итоге мы получили несколько #ifdefs, здесь полезные комментарии: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)


2
Как обычно окна не похожи на другие :)
mathk

Можно ли подать «сигнал 0», чтобы продолжить выполнение программы в приостановленном состоянии? Было бы неплохо иметь возможность использовать «n» или «s» с этого момента без использования «c».
Джейсон Дусетт

2
@JasonDoucette Если вы действительно хотите, чтобы программа остановилась, вы можете добавить breakpoint()в свою программу функцию (она может быть пустой или просто содержать оператор печати) и добавить break breakpointв свой ~/.gdbinit.
Джейсон Орендорф

26

Заглянув сюда , я нашел следующий способ:

void main(int argc, char** argv)
{
    asm("int $3");
    int a = 3;
    a++;  //  In gdb> print a;  expect result to be 3
}

Мне это кажется хакерским. И я думаю, что это работает только на архитектуре x86.


3
И только с компиляторами, поддерживающими синтаксис сборки AT&T. В частности, компилятор Microsoft ( cl.exe) не поддерживает этот синтаксис, но использует другой синтаксис.
Håvard S,

вопрос был о linux, поэтому я думаю, мы можем предположить, что синтаксис gcc будет работать для x86.
js.

Кстати, я попробовал описанное выше на своей машине x86, и это сработало. Мне было любопытно, есть ли лучший способ сделать это. Похоже, что есть.
J. Polfer

2
Я использую mingw в окнах, поэтому другие предложения мне не помогут. Повышение сигнала SIGINT просто завершает приложение, SIGTRAP не определен в заголовках mingw ... Использование инструкции int фактически отправляет SIGTRAP, и gdb красиво прерывается в соответствующей строке.
Machta


12

__asm__("int $3"); должно сработать:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    __asm__("int $3");
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}

1
Мне это нравится #define, так что мне не нужно запоминать синтаксис. Я разбрызгивал его по всему коду, иногда вместо assert(), поскольку остановка отладчика позволяет мне исследовать все переменные и стек. И, конечно же, как и assert, мне не нужно удалять его для производственного кода
Mawg говорит восстановить Монику

Интересно, что у этого есть 10 голосов, когда ограничения вопроса «Linux» и «GDB» предоставляют множество возможностей помимо обращения к сборке, которая всегда должна быть последним средством ради переносимости, если ничего другого. Пожалуйста, посмотрите некоторые другие ответы.
Бенджамин Кроуфорд Ctrl-Alt-Тут

5

Прискорбно видеть так много ответов, не использующих выделенный сигнал для программных точек останова SIGTRAP:

#include <signal.h>

raise(SIGTRAP); // At the location of the BP.

1

В OS X вы можете просто позвонить std::abort()(это может быть то же самое в Linux)


Какая библиотека?
Alex

Это часть стандартной библиотеки C ++ и кроссплатформенность, в которой существуют компиляторы, совместимые с C ++ 11. Однако это вызывает сигнал SIGABRT, который в данном случае не является подходящим сигналом.
Бенджамин Кроуфорд Ctrl-Alt-Tut
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.