Встановіть точку розриву в коді 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.
Стюарт Голодець

@Stuart - виправлено. Треба було це зробити деякий час тому.
Дж. Полфер

4
@ J.Polfer: Хоча return 0це не потрібно, і це лише шум!
Гонки легкості на орбіті

Відповіді:


107

Один із способів - сигналізувати про переривання:

#include <csignal>

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

В:

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

ОНОВЛЕННЯ : MSDN стверджує, що Windows насправді не підтримує SIGINT, тому якщо портативність викликає занепокоєння, ви, ймовірно, краще використовуватимете SIGABRT.


Так, це має працювати в операційних системах / компіляторах / налагоджувачах.
Håvard S

1
Я не знаю інших відладчиків, але gdb є досить гнучким щодо обробки сигналів .
Каскабель

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'.
Jason Doucette

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.

BTW - я спробував вище сказати на своїй машині x86, і це спрацювало. Мені було цікаво, чи є кращий спосіб зробити це. Схоже, є.
Дж. Полфер

2
Я використовую mingw на windows, тому інші пропозиції не можуть мені допомогти. Підвищення сигналу SIGINT просто припиняє додаток, SIGTRAP не визначається в заголовках mingw ... Використання інструкції int фактично надсилає SIGTRAP і gdb чудово переривається на відповідний рядок.
Махта

У Linux int 3піднімає SIGTRAP.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

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(), оскільки зупиняючи дебіггер, давайте я вивчу всі змінні та стек. І, звичайно, як і стверджувати, мені не доведеться видаляти його для виробничого коду,
каже Мауг, щоб відновити Моніку

Цікаво, що це має 10 надбавок, коли обмеження питань "Linux" та "GDB" дають безліч варіантів поза межами звернення до збірки, що завжди повинно бути крайнім заходом заради переносимості, якщо нічого іншого. Будь ласка, подивіться деякі інші відповіді.
Бенджамін Кроуфорд Ctrl-Alt-Tut

5

Невтішно бачити стільки відповідей, не використовуючи виділений сигнал для програмних точок прориву SIGTRAP:

#include <signal.h>

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

1

В OS X можна просто зателефонувати std::abort()(це може бути те саме в Linux)


Яка бібліотека?
Олексій

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