Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> and C++ where you don't

what do you mean ? in which case don't you get a backtrace in C++ ?



If 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.


C/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 ()


Try 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.


> 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)


As they are specifically talking about new programmers, using gdb in your example effectively communicates and confirms their point.


> As they are specifically talking about new programmers, using gdb in your example effectively communicates and confirms their point

New programmers would be using IDEs, press the green arrow "play" button and launch the app with the debugger enabled without them knowing, which would cause the editor to jump directly to where the issue is


When I was in school there was some server we SSH'd into and compiled shit with GCC, and we were not told what gdb is


I'm sorry but there are bad teachers / courses everywhere, that does not reflect on the technology (though C++ has it really bad for some reason). When I was in school learning how to debug was one of the first classes we had.

If they were teaching you rust be sure that they wouldn't have told you about cargo either.


That is a reflection of your school, and not the language.

I'm a self taught C/C++ programmer, learning and becoming comfortable with gdb was one of the first few things I taught myself after learning how to compile code into a binary back in the 1990's.


GDB is not an advanced tool.


That'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.


Being able to use a debugger should be an essential part of any curriculum. GDB is only an advanced tool if you're an advanced user; it's useful for the entire spectrum of programming language users.


In 2006 when I did this in school it most definitely was not part of the curriculum


Note the "should"; most curricula could use a bit of improvement :)


It was on my school back in 1990 on a tiny Portuguese town, with Turbo Basic and Turbo Pascal as introductory languages.


You clearly did not learn to develop with an IDE, especially not Visual Studio.


I'm not sure where you're going with this?


That everything is relative. That gdb absolutely is advanced and complicated dark magic if you’ve learned to code/debug on and been spoiled by an easy to use IDE.


I don't think so. Programmers should be taught what is going on under the hood if they're learning system languages like c/c++/rust


The 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.


Beginners should be using a friendly IDE to start with.


That's just a poor default, I guess. Rust compiles debug builds unless you tell it not to.


C/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).


This may have changed since the days of my youth


Whether 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.


Don't you need to add

  [profile.release]
  debug = true
to make this work?


Oh, you may be right. My company's main codebase does indeed have that; I had assumed it was the default.


I 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.


IIRC this is correct, libstd is built in release mode but with debuginfo.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: