Set breakpoint in C or C++ code programmatically for gdb on Linux
Solution 1
One way is to signal an interrupt:
#include <csignal>
// Generate an interrupt
std::raise(SIGINT);
In C:
#include <signal.h>
raise(SIGINT);
UPDATE: Microsoft Docs says that Windows doesn't really support SIGINT
, so if portability is a concern, you're probably better off using SIGABRT
.
SIGINT is not supported for any Win32 application. When a CTRL+C interrupt occurs, Win32 operating systems generate a new thread to specifically handle that interrupt. This can cause a single-thread application, such as one in UNIX, to become multithreaded and cause unexpected behavior.
Solution 2
By looking here, I found the following way:
void main(int argc, char** argv)
{
asm("int $3");
int a = 3;
a++; // In gdb> print a; expect result to be 3
}
This seems a touch hackish to me. And I think this only works on x86 architecture.
Solution 3
In a project I work on, we do this:
raise(SIGABRT); /* To continue from here in GDB: "signal 0". */
(In our case we wanted to crash hard if this happened outside the debugger, generating a crash report if possible. That's one reason we used SIGABRT. Doing this portably across Windows, Mac, and Linux took several attempts. We ended up with a few #ifdefs, helpfully commented here: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)
Solution 4
Disappointing to see so many answers not using the dedicated signal for software breakpoints, SIGTRAP
:
#include <signal.h>
raise(SIGTRAP); // At the location of the BP.
On MSVC/MinGW, you should use DebugBreak
, or the __debugbreak
intrinsic. A simple #ifdef
can handle both cases (POSIX and Win32).
Solution 5
__asm__("int $3");
should work:
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;
}
J. Polfer
Updated on February 15, 2021Comments
-
J. Polfer over 3 years
How can I set a breakpoint in C or C++ code programatically that will work for gdb on Linux?
I.e.:
int main(int argc, char** argv) { /* set breakpoint here! */ int a = 3; a++; /* In gdb> print a; expect result to be 3 */ return 0; }
-
Stuart Golodetz over 13 yearsVery much a side note (sorry to nitpick), but if you're worried about portability then you're probably also worried about correctness - hence
int main
rather thanvoid main
. -
J. Polfer over 13 years@Stuart - Fixed. Should have done that a while ago.
-
Lightness Races in Orbit about 9 years@J.Polfer: The
return 0
is not necessary, though, and is just noise! -
Jimmio92 over 2 years@LightnessRacesinOrbit the
return 0;
is 100% necessary. Besides the warning your compiler should throw at you, this can corrupt the stack on older/embedded systems, and as such should ALWAYS be done out of habit and correctness. Forget a return in other places in your code and you're guaranteed to pay for it on modern desktop systems, too. -
handle over 2 years
-
Jonathan Wakely over 2 years@Jimmio92 No,
main
is special in all versions of C++ and also in C since C99. Reaching the final}
ofmain
without returning is equivalent toreturn 0;
so the compiler should not warn, and it cannot corrupt anything. In C89 it's undefined, but that's the exception to the rule, not the general case as you imply by "100% necessary". C++98 and C99 are not new, time to update your knowledge ;-) -
Jimmio92 over 2 years@JonathanWakely Maybe you meant that comment as helpful, but I took it the polar opposite. So let me address as calmly as I can muster. One, I mentioned your own code must return if you tell the compiler to expect it. Two, it should warn you. Just because the standard automatically fixes your mistakes because of a wrapper around
main
doesn't mean you should make them. Three, I use C++17 in clang. Four, I have literally encountered this as a bug in low level code. C/C++ can be used without the standard library and without an operating system. Take your "learn it again" attitude elsewhere. -
Jonathan Wakely over 2 yearsIt's not a mistake though. The standard guarantees the behaviour, relying on that is not a mistake. You said "100% necessary" and that's just wrong.
-
-
Håvard S over 13 yearsYes, this should work across operating systems/compilers/debuggers.
-
Cascabel over 13 yearsI don't know other debuggers, but gdb is pretty flexible about signal handling.
-
Håvard S over 13 years@Jefromi Most decent debuggers have knobs and switches that allow you to control how they handle various signals.
-
Håvard S over 13 yearsAnd only with compilers supporting the AT&T assembly syntax. In particular, Microsoft's compiler (
cl.exe
) does not support this syntax, but uses a different syntax. -
js. over 13 yearsthe question was about linux, so i guess we can assume that the gcc syntax will work for x86.
-
J. Polfer over 13 yearsBTW - I did try the above on my x86 machine and it did work. I was curious if there was a better way of doing it. Looks like there is.
-
mathk about 13 yearsAs usual windows does not look like the others :)
-
JBRWilkinson almost 12 yearsWe found SIGTRAP better on some Unices
-
Machta about 10 yearsI am using mingw on windows so the other suggestions can't help me. Raising SIGINT signal just terminates the application, SIGTRAP is not defined in mingw headers... Using int instruction actually sends SIGTRAP and gdb breaks nicely on the appropriate line.
-
Fernando Gonzalez Sanchez over 9 yearsin Windows, MSVC you can use __debug_break, DebugBreak or _asm {int 3}.
-
Morix Dev almost 9 years@FernandoGonzalezSanchez: actually the function name is
__debugbreak()
and NOT__debug_break()
, as you can see here -
Ciro Santilli OurBigBook.com over 8 yearsIn Linux,
int 3
raises a SIGTRAP. -
Mawg says reinstate Monica almost 8 yearsI like to
#define
this, so that I don't have toi remember the syntax. I have it sprinkled throughout my code, sometimes in place ofassert()
, since stopping the debiugger let's me examine all variables & the stack. And, of course, like assert, I don't have to remove it for production code -
Jason Doucette over 7 yearsIs it possible to issue "signal 0" to continue program the program in a paused state? It would be nice to be able to use 'n' or 's' from this point, without a 'c' being issued.
-
Jason Orendorff over 7 years@JasonDoucette If you really just want the program to pause, you might want to add a
breakpoint()
function in your program (it can be empty or just contain a print statement) and addbreak breakpoint
to your~/.gdbinit
. -
Alex almost 7 yearsWhich library ?
-
Dellowar over 6 yearsNice and spooky. I like it.
-
Benjamin Crawford Ctrl-Alt-Tut over 4 yearsThis is part of the standard C++ library and is cross-platform where C++11-compliant compilers exist. This however, raises SIGABRT, which is not really an appropriate signal to raise in this instance.
-
Benjamin Crawford Ctrl-Alt-Tut over 4 yearsInteresting that this has 10 upvotes when the question constraints of "Linux" and "GDB" give plenty of options outside of resorting to assembly, which should always be a last resort for portability's sake if nothing else. Please see some of the other answers.
-
ergohack over 3 yearsSome platforms (e.g. Msys2), do not have
SIGTRAP
defined. -
Ralph almost 3 years@BenjaminCrawfordCtrl-Alt-Tut In this specific case conceptually raising a SIGTRAP signal is a good idea. Of course the answer could be improved by specifying to do
raise()
instead, but it is valuable to see what goes behind it. -
Benjamin Crawford Ctrl-Alt-Tut over 2 years@Ralph
int $3
is only "what goes behind it" on x86 systems, which the question doesn't specify...