digitalmars.D.learn - How to debug D on Linux
- Roguish (9/9) Jan 13 2021 How to debug D? My little trial app gives a segmentation fault.
- Roguish (5/6) Jan 13 2021 I've discovered that GDB works with the binary generated by the D
- Roguish (5/7) Jan 13 2021 One specific question I have is: what's the difference between -g
- drug (2/10) Jan 13 2021 https://stackoverflow.com/questions/17392200/debugging-dmd-generate-prog...
- drug (5/8) Jan 13 2021 Short answer - sometimes the compiler does not emit a stackframe (due to...
- Roguish (4/6) Jan 13 2021 OK, so -gs prevents a certain optimization that would make
- Adam D. Ruppe (38/41) Jan 13 2021 -debug enables the `debug` keyword inside the D code itself. This
- Roguish (11/32) Jan 13 2021 Thanks, that's very clear.
- evilrat (10/12) Jan 13 2021 if you are looking for back trace someone recently posted a hint
- Roguish (2/8) Jan 13 2021 Good tip, thanks.
- Rikki Cattermole (13/18) Jan 13 2021 From LDC (ldc specific):
- Roguish (11/12) Jan 13 2021 Clear, thanks.
- Daniel Kozak (10/23) Jan 13 2021 There are 3 main compilers which share same frontend,
- user1234 (27/34) Jan 13 2021 -g : generate dwarf info, the debug info, the most important
- Roguish (3/5) Jan 13 2021 I've used GDB before, but I've forgotten nearly all of it. Your
How to debug D? My little trial app gives a segmentation fault. Probably a null pointer somewhere, which I could find simply by reading my code. But I'm puzzled that the program outputs very little helpful info when it crashes, even though I've compiled with all the debug options I could find in the docs: -g -gs -gf -debug -d-debug Still all I get at runtime is Segmentation fault (core dumped) Surely it should be possible to get at least a stack trace?
Jan 13 2021
On Wednesday, 13 January 2021 at 13:22:01 UTC, Roguish wrote:How to debug D? be possible to get at least a stack trace?I've discovered that GDB works with the binary generated by the D compiler, so that's great. Anything else I need to know when debugging on Linux, without an IDE?
Jan 13 2021
On Wednesday, 13 January 2021 at 13:30:48 UTC, Roguish wrote:Anything else I need to know when debugging on Linux, without an IDE?One specific question I have is: what's the difference between -g and -debug and -d-debug? Also, what does it mean to "always emit a stackframe" (compiler option -gs) ?
Jan 13 2021
On 1/13/21 4:47 PM, Roguish wrote:On Wednesday, 13 January 2021 at 13:30:48 UTC, Roguish wrote:https://stackoverflow.com/questions/17392200/debugging-dmd-generate-program-through-gdbAnything else I need to know when debugging on Linux, without an IDE?One specific question I have is: what's the difference between -g and -debug and -d-debug? Also, what does it mean to "always emit a stackframe" (compiler option -gs) ?
Jan 13 2021
On 1/13/21 4:47 PM, Roguish wrote:Also, what does it mean to "always emit a stackframe" (compiler option -gs) ?Short answer - sometimes the compiler does not emit a stackframe (due to optimization for example). In general if you are able to debug your binary by gdb then you don't need to worry this flag. I skip long answer, sorry :-) But you can google about stack frame.
Jan 13 2021
On Wednesday, 13 January 2021 at 14:13:07 UTC, drug wrote:Short answer - sometimes the compiler does not emit a stackframe (due to optimization for example).OK, so -gs prevents a certain optimization that would make debugging harder in certain situations. Thanks for clearing that up.
Jan 13 2021
On Wednesday, 13 January 2021 at 13:47:55 UTC, Roguish wrote:One specific question I have is: what's the difference between -g and -debug and -d-debug?-debug enables the `debug` keyword inside the D code itself. This lets you bypass other rules temporarily. For example void foo() pure { writeln("called foo"); } Normally, that wouldn't compile, since writeln is not pure. But if you do void foo() pure { debug writeln("called foo"); } It is allowed. Without the `-debug` switch, that line is just ignored, it is not compiled. With the `-debug` switch, that line is allowed - and it bypasses the pure restriction. It does NOT do anything related to running D in debuggers like gdb, it just enables code guarded by that debug keyword.-g-g is what compiles in the information gdb uses. This info is used to print function names in stack traces, make breakpoints by file and line number, etc. You can use -g and -debug together or independently or whatever depending on what exactly you want to do. Now, some general tips on using D with gdb: * Segfaults should be run inside the debugger to get the stack trace. If your program did "Segmentation fault (core dumped)", you can fire up gdb after the fact on it. Check that directory for a .core file and then run `gdb program that.core` to inspect it. * Running a program in gdb may sometimes say "program received SIGUSR1" and pause. The commands handle SIGUSR1 noprint handle SIGUSR2 noprint will skip this. SIGUSR1/2 are used by the GC when doing collections so you probably don't care about it. You can put those commands i your ~/.gdbinit to run every time. * Running `gdb --args ./yourprogram --DRT-trapExceptions=0` will break on any uncaught exception so you can inspect that stuff. Super useful if you get one of those.
Jan 13 2021
On Wednesday, 13 January 2021 at 14:13:11 UTC, Adam D. Ruppe wrote:-debug enables the `debug` keyword inside the D code itself. This lets you bypass other rules temporarily. For example ... It does NOT do anything related to running D in debuggers like gdb, it just enables code guarded by that debug keyword.Thanks, that's very clear.* Segfaults should be run inside the debugger to get the stack trace. If your program did "Segmentation fault (core dumped)", you can fire up gdb after the fact on it. Check that directory for a .core file and then run `gdb program that.core` to inspect it.It seems on my system no .core file gets generated, even though the program outputs "Segmentation fault (core dumped)". At least it's not present in the directory from where I compile and run the program, nor is it in /var/lib/systemd/coredump where, according to systemd-coredump's documentation, it should go by default. Anyway, I'm guessing this is a config problem with my Linux, rather than anything to do with D's compiler or runtime.* Running a program in gdb may sometimes say "program received SIGUSR1" and pause. The commands handle SIGUSR1 noprint handle SIGUSR2 noprint will skip this. SIGUSR1/2 are used by the GC when doing collections so you probably don't care about it. You can put those commands i your ~/.gdbinit to run every time. * Running `gdb --args ./yourprogram --DRT-trapExceptions=0` will break on any uncaught exception so you can inspect that stuff. Super useful if you get one of those.Yes! Excellent tips these. Thank you.
Jan 13 2021
if you are looking for back trace someone recently posted a hint for linux where there is no back trace by default is to import core.sys.linux.backtrace or something that has back trace info and using it in exception handler for runtime to print the stack trace. https://dlang.org/phobos/core_runtime.html#.defaultTraceHandler On Wednesday, 13 January 2021 at 13:47:55 UTC, Roguish wrote:One specific question I have is: what's the difference between -g and -debug and -d-debug?no idea what is -d-debug, but -g will emit debug info for debugger, and -debug will turn on certain features such as contracts and asserts even in release builds.
Jan 13 2021
On Wednesday, 13 January 2021 at 14:13:17 UTC, evilrat wrote:if you are looking for back trace someone recently posted a hint for linux where there is no back trace by default is to import core.sys.linux.backtrace or something that has back trace info and using it in exception handler for runtime to print the stack trace. https://dlang.org/phobos/core_runtime.html#.defaultTraceHandlerGood tip, thanks.
Jan 13 2021
On Wednesday, 13 January 2021 at 13:47:55 UTC, Roguish wrote:On Wednesday, 13 January 2021 at 13:30:48 UTC, Roguish wrote:From LDC (ldc specific): --d-debug[=<level/idents>] - Compile in debug code >= <level> or identified by <idents> --d-version=<level/idents> - Compile in version code >= <level> or identified by <idents> From dmd: -debug compile in debug code -debug=<level> compile in debug code <= level -debug=<ident> compile in debug code identified by ident -version=<level> compile in version code >= level -version=<ident> compile in version code identified by ident Same thing.Anything else I need to know when debugging on Linux, without an IDE?One specific question I have is: what's the difference between -g and -debug and -d-debug?
Jan 13 2021
On Wednesday, 13 January 2021 at 14:17:51 UTC, Rikki Cattermole wrote:Same thing.Clear, thanks. I'm just discovering today that DMD and LDC are two different compilers. I got a different impression from the following webpage, which claims that ldmd2 is a wrapper invoking ldc2. https://stackoverflow.com/questions/35515138/ldc2-vs-ldmd2-whats-the-difference Perhaps this is just a peculiarity of how D is distributed on Debian? I simply installed the 'ldc' package from Debian's official repos, and that contains both a binary called ldc2 and one called ldmd2.
Jan 13 2021
On Wed, Jan 13, 2021 at 4:10 PM Roguish via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:On Wednesday, 13 January 2021 at 14:17:51 UTC, Rikki Cattermole wrote:There are 3 main compilers which share same frontend, DMD (using own backend), LDC2(llvm backend) a GDC(gcc backend) ldmd and gdmd are some wrappers to make similar interface for compiling with any of these compilers. So generally dmd, gdmd and ldmd2(on some distribution ldmd without 2) should have accept same args So calling <dmd or gdmd or ldmd2> -arg1 -arg2 -arg3 should do the same but with different compilers behind the scene.Same thing.Clear, thanks. I'm just discovering today that DMD and LDC are two different compilers. I got a different impression from the following webpage, which claims that ldmd2 is a wrapper invoking ldc2. https://stackoverflow.com/questions/35515138/ldc2-vs-ldmd2-whats-the-difference Perhaps this is just a peculiarity of how D is distributed on Debian? I simply installed the 'ldc' package from Debian's official repos, and that contains both a binary called ldc2 and one called ldmd2.
Jan 13 2021
On Wednesday, 13 January 2021 at 13:47:55 UTC, Roguish wrote:On Wednesday, 13 January 2021 at 13:30:48 UTC, Roguish wrote:-g : generate dwarf info, the debug info, the most important -debug : compiles the debug statements, e.g debug logging. not so important, this is a conditional compilation feature. -gs : always emit a prelude/prologue. but dmd pretty much always do that even when not required (sigh). You really mostly only requires -g. Then you have to learn gdb. A few basis to get started, a session for a segfault is often like $ gdb ./myapp $ run and when it crashes, note the source position, additionally $ bt $ p somevar $ p some.more.complex.expression may already give interesting infos. If not, during a second session you will rather put breakpoints to see what happens before the access violation and step from that breakpoint to the code that accesses unowned memory. $ gdb ./myapp $ break <somefile>.d <linenum> $ run and then step by step, each time it pauses you inspect the interesting stuff. Note that I may be wrong on the syntax of the commands as I always use an IDE GUI.Anything else I need to know when debugging on Linux, without an IDE?One specific question I have is: what's the difference between -g and -debug and -d-debug? Also, what does it mean to "always emit a stackframe" (compiler option -gs) ?
Jan 13 2021
On Wednesday, 13 January 2021 at 14:27:48 UTC, user1234 wrote:You really mostly only requires -g. Then you have to learn gdb. A few basis to get startedI've used GDB before, but I've forgotten nearly all of it. Your recap of the basics is appreciated. :-)
Jan 13 2021