3 ms·
dbg! looks neat. It made me wonder if any of the statically typed compiled languages have an equivalent of Ruby's binding.pry or JS's debugger call? That is, so
by ainar-g 8y ago
dbg! looks neat. It made me wonder if any of the statically typed compiled languages have an equivalent of Ruby's binding.pry or JS's debugger call? That is, something like
x = foo();
invoke_debugger(); // An interactive console appears here.
y = bar(x)
- xtian 8y agogdb or lldb provide debugger functionality for native code, but you don’t set breakpoints programmatically.
- roblabla 8y agoYou can, actually. At least in x86 asm, you just have to add an int3 instruction to get a breakpoint (requires OS support of course).
- steveklabnik 8y agoIn theory you could inline assembly "int 3" or the like, but I'm not really aware of anyone doing things like this directly.
- simias 8y agoWell for "regular" code if you want a breakpoint it makes more sense to use the debugger anyway. If you generate machine code however (for a JIT for instance) it's definitely a useful trick since adding debugger support for generated code, while possible, is often pretty tricky and non-portable.
- klibertp 8y agoThe "statically typed" part is not a big issue (there are many statically-typed languages with REPLs, after all), but "compiled" could be. For example, while you can stick a read-eval-print-loop anywhere in your code when using Racket, you can't see any non-top-level bindings there, because they may or may not be there during runtime. The compiler is free to inline or fold or remove any such binding at will (as long as the behavior of the program remains the same). There's a debugger for Racket, and it's also possible to use it programmatically, but you cannot just call it like `debugger;` in JavaScript: you need to recompile a module so that it uses (a lot of) heavy instrumentation and only then you can set a breakpoint, also from the inside. I'd expect something like this: https://github.com/krixano/Lydrige https://github.com/krixano/Lydrige to have it easy in this regard - it's a statically-typed but interpreted language.
- jcranmer 8y agoOn x86 systems, a breakpoint is implemented by replacing the byte with the "int3" instruction. For Unix systems, this is the SIGTRAP signal. So invoke_debugger() that boils down to asm("int3") would suffice, if you were already on a debugger. Well, the trouble is knowing if you need to spawn a debugger. On Windows, there's a nice API for checking if you're being debugged (IsDebuggerPresent). On Linux, you have to read /proc/self/status to see if there is somebody running ptrace on you. On other Unixes, well, the only trick is trying to spawn another process to ptrace you and hope it works. It is possible, just tricky.
- lzybkr 8y agoVisual C++ has the __debugbreak() intrinsic function. If you have JIT debug enabled, you will be prompted to attach your debugger to the process when hitting such a breakpoint.
- SCHiM 8y agoI use this sometimes with some C/C++ code. Mostly, if I want a break somewhere I do this: *(int*)0 = 1; Which will result in a crash, I attach my debugger, run the code and if it reaches that line it will break and I can inspect everything I want. It's easier than adding a __asm(int3) because it's cross platform. On windows for example it's not possible to perform inline assembly in x64 builds, and compiler intrinsics are not portable.