Программная установка точки останова в коде 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
источник
Да, это должно работать во всех операционных системах / компиляторах / отладчиках.
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
В Linux int 3вызывает SIGTRAP.
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
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;
}
hek2mgl
источник
1
Мне это нравится #define, так что мне не нужно запоминать синтаксис. Я разбрызгивал его по всему коду, иногда вместо assert(), поскольку остановка отладчика позволяет мне исследовать все переменные и стек. И, конечно же, как и assert, мне не нужно удалять его для производственного кода
Mawg говорит восстановить Монику
Интересно, что у этого есть 10 голосов, когда ограничения вопроса «Linux» и «GDB» предоставляют множество возможностей помимо обращения к сборке, которая всегда должна быть последним средством ради переносимости, если ничего другого. Пожалуйста, посмотрите некоторые другие ответы.
Бенджамин Кроуфорд Ctrl-Alt-Тут
5

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

#include <signal.h>

raise(SIGTRAP); // At the location of the BP.
Бенджамин Кроуфорд Ctrl-Alt-Tut
источник
1

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

дакап
источник
Какая библиотека?
Alex
Это часть стандартной библиотеки C ++ и кроссплатформенность, в которой существуют компиляторы, совместимые с C ++ 11. Однако это вызывает сигнал SIGABRT, который в данном случае не является подходящим сигналом.
Бенджамин Кроуфорд Ctrl-Alt-Tut