8 ms·
Better line numbers is huge. Actually huge for people leaning rust. In a pretty big way it's like the difference between Java where you get a stack trace (where
by computerphage 7y ago
Better line numbers is huge. Actually huge for people leaning rust. In a pretty big way it's like the difference between Java where you get a stack trace (where you mostly care about the live number all the way at the bottom) and C++ where you don't. When I tutored students in college that was one of the most salient differences to students who were just starting out. They would say things like "C++ is hard because you don't even get a stack trace". Sure, that's a naive view of the differences between the languages, but it's a real view that beginners see.
- jcelerier 7y ago> and C++ where you don't what do you mean ? in which case don't you get a backtrace in C++ ?
- neutronicus 7y agoIf you compile without debug symbols you don't get a trace after a seg fault. If you're taking first year programming and they give you a compiler incantation that doesn't include -g that will be your experience.
- saagarjha 7y agoThat's just a poor default, I guess. Rust compiles debug builds unless you tell it not to.
- neutronicus 7y agoThis may have changed since the days of my youth
- umanwizard 7y agoWhether a build is debug or release is independent of whether it contains debug symbols. Both `cargo build` and `cargo build --release` produce builds with debug symbols.
- saagarjha 7y agoDon't you need to add [profile.release] debug = true to make this work?
- umanwizard 7y agoOh, you may be right. My company's main codebase does indeed have that; I had assumed it was the default.
- Freaky 7y agoI think you still get symbols for libstd without that. I can see why that would lead to confusion - stripping a plain --release build still saves a few MB.
- steveklabnik 7y agoIIRC this is correct, libstd is built in release mode but with debuginfo.
- ComputerGuru 7y agoC/C++ compile some weird default of neither debug nor optimized, basically the least helpful thing anyone could want (no performance optimizations, no debug symbols, and maybe-maybe-not asserts depending on if the standard library you’re using or the libraries you’re depending on used #if NDEBUG or #if DEBUG to gate the assertion checks. And not optimized for size either, if that’s what you were wondering).
- umanwizard 7y agoC/C++ programs will normally have function names in backtraces, just not line numbers. $ cat test.c int g() { int *p = 0; *p = 5; } int f() { g(); } int main() { f(); } $ cc test.c $ ./a.out [1] 3377 segmentation fault (core dumped) ./a.out $ gdb -q a.out core Reading symbols from a.out... (No debugging symbols found in a.out) [New LWP 3377] Core was generated by `./a.out'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000557379b7613d in g () (gdb) bt #0 0x0000557379b7613d in g () #1 0x0000557379b76158 in f () #2 0x0000557379b7616d in main ()
- wahern 7y agoTry with -O3. Another wrinkle is that the symbol names of extern functions need to be in the binary regardless of debug level, though the main binary is a special case, unlike shared libraries. So you'll get different results again if you add -fPIC -rdynamic (or possibly just -fPIC) to -O3, similar results as-if you compiled a library with -O3 -fPIC -shared. But then if you define f and g as statically scoped -fPIC -rdynamic won't change the behavior. It follows that there's a potential conflict between code optimization and the ability to determine function names and line numbers for a trace. To preserve the ability to associate the programer counter (PC) to distinct function names and line numbers a compiler might need to abstain from completely inlining, merging, eliding, or otherwise optimizing some functions and code blocks (though that doesn't mean it needs to preserve actual function call behavior). People will endlessly debate the cost+benefit, but it's something to keep in mind for performance critical code blocks.
- jcelerier 7y ago> If you compile without debug symbols you don't get a trace after a seg fault. uh... no. given volatile char* foo = 0x0; struct crasher { void crash() { *foo = 1; } }; int main() { crasher c; c.crash(); } and $ g++ foo.cpp $ ./a.out then $ coredumpctl gdb gives me (gdb) bt #0 0x000055cea1ff6187 in crasher::crash() () #1 0x000055cea1ff615c in main () The only case when you wouldn't get function names is if your binary has been stripped manually (or as part of a build system step)
- turndown 7y agoAs they are specifically talking about new programmers, using gdb in your example effectively communicates and confirms their point.
- saagarjha 7y agoGDB is not an advanced tool.
- aspaceman 7y agoThe whole point of this entire discussion was that it's an additional tool where beginners are used to the runtime spitting out a backtrace for them.
- pjmlp 7y agoBeginners should be using a friendly IDE to start with.
- viraptor 7y agoThat's a naive view. Depends who's learning. Is C++ their 5th language and they know how to read resulting assembly? Is it their first experience at 10yo and they're struggling with what variables and types are? Anywhere in between? Gdb beyond what the learning person can comfortably handle at the time and that's what matters.
- saagarjha 7y agoC++ does give you a stack trace; you just need to set some things up before it does (namely, use a debugger). Rust does the same except it tells you what you need to do (set an environment variable).
- nicoburns 7y agoYou get this single-line error without enabling backtraces however. So the fact that this is now useful for the common case of "which line caused the error" is a pretty big deal.
- est31 7y agoYeah for backtraces to work you also need to have debug info enabled which puts a major burden onto linking time. And once they are enabled, you have to scan the backtrace carefully to filter out the parts that are in the panic library. The line message is displayed prominently and thus allows for a much faster development cycle in finding the error.
- umanwizard 7y agoBacktraces even without line numbers are still quite useful, as long as they have function names.
- nicoburns 7y agoI mean, they're better than nothing. But they leave you guessing at exactly where the error is if you do similar operations more than once in your function. A line number is much better.
- ComputerGuru 7y agoJust as a life tip (regardless of language): Without a line number you would get an offset, which you can use gdb or addr2line to go back to line numbers if you have the unstripped binary or debug symbols available (or the source, but that’s not necessarily deterministic).
- deleted 7y ago[deleted]
- malkia 7y agoTo get the callstack before the exceptions unroll, on Windows you can utilize https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-addvectoredexceptionhandler https://docs.microsoft.com/en-us/windows/win32/api/errhandli... but then you would have to skip few specific exceptions (that are normally issued, since these come really fast, and you'll see them)
- quietbritishjim 7y agoUnless I've misunderstood the context, you can just open the "exceptions" debugging pane and check a few checkboxes. Then when the exception gets thrown the whole thing stops in a debugger and you can do all the usual things including look at the stack trace, indirect local variables at the throw point, etc.
- ComputerGuru 7y agoThat’s for doing it in code, without a debugger attached.
- pjmlp 7y agoOn Windows there is always Dr.Watson to give an helping hand, even without debugger.
- malkia 7y agoIs this still a thing? I've never encountered Dr.Watson recently. I do remember really long time ago Soft-ICE - that was exciting back then - debugging DOS/Windows really low level (I think it was through serial port on another machine)....
- quietbritishjim 7y agoAh OK. But the context was "students in college ... who were just starting out". I would say they would be running their programs, at least initially, in an IDE. And they should be using an IDE to develop: getting students to develop without IDE support is just unfair (although I know people get religious about using a text editor for code development). This is how I keep finding new grads who have no idea how to use a debugger e.g. just set a breakpoint and inspect variables.
- bithavoc 7y agoI agree, I’m glad Rust is addressing it, one the most annoying things about D is the lack of stack traces and is the reason I stopped using it and switched to Go entirely, I wrote a blog post[0] about D vs Go and their approaches to stack traces, at least Rust acknowledges the problem. [0] https://bithavoc.io/blog/2020/01/01/go-binary-size-descision/ https://bithavoc.io/blog/2020/01/01/go-binary-size-descision...