Don't debug -O3, or -O2 for that matter. Debug a separate debug build without optimizations, or don't heavily optimize your release build if you want to debug that (you know that obviously).
Even with optimizations disabled, debugging C++ can be quite painful. Only add a little template stuff to the source code, and a few "zero-cost" methods like indexing operators or cast operators, and it quickly becomes painful to step through code.
There should be a way to avoid stepping through boilerplate methods, but apart from specifying string patterns to exclude methods by name -- not inline with the method but in a separate debugging configuration (which is very very annoying).
The only solution I know is to use C++ features very lightly. Any other practical options?
Can Just My Code help if it is precisely my code that I want to skip over? I believe it does not -- IIUC it works based on modules i.e. the DLL that contains the machine code. IOW it doesn't even help if I move the "zero-cost" stuff to a separate source file -- templates and other stuff that have to be instanciated or inlined won't be separable from the code that I want to debug based on the module they're running in.
> Also, there are scenarios where debugging without optimizations isn't an option.
There are scenarios where debugging isn't an option in the first place. Doesn't mean that I should have to suffer in the typical case where debugging with no or only light optimizations is perfectly viable.
An acceptable solution I guess would be to have a [DebuggerHidden] function attribute as I found for C#. Didn't find one for C++.
Well, if we are going down tiny details about what to skip, there are lots of C preprocessor stuff, standard library functions implementated in crazy ways for ISO/POSIX compliance, and own abstractions/functions, that I might also want to skip over.
Well, don't go down that path. Stop bringing decreasingly relevant points. You are too argumentative.
"standard library functions implemented in crazy ways" is what I though about once in my life, when writing a toy compiler whose output was linked to libc. Such "crazy functions" do exist but but apart from libc having little relevance in this context it's not at all like debugging a line my_arr[i] = make_arr_elem(). That is a reasonably looking line but can easily contain two more function calls than is immediately visible, and it's very very tiring in actual practice to step through such code. The only solution I've found is to be careful to use very little such magic.
The general way that C is written in practice is that you don't have 3 function calls per line. So even if you have lots abstractions and macros in place that you would like to ignore (which can happen, but it's more rare than common) you can still skip over them (e.g. F10 in VS).
The complaint above isn't that gdb is hard, it's that the binary with debug info doesn't correlate very well with the source code after optimisations.
Bugs tend to disappear on me when I change the optimiser flags or run the thing under gdb though. I've also had a program valgrind-clean that segfaults when run without valgrind. It's a confusing world out there.
Debugging optimized binaries is harder than debugging non-optimized ones, and requires more advanced debugging skills and gdb knowledge.
There is a reason why crash dumps on optimized builds used to be called "guru meditation".
One useful skill to get started is learning how to get at data and print it through various levels of complex C++ data structures, which might require leaning on the python API to stay sane.
> Bugs tend to disappear on me when I change the optimiser flags or run the thing under gdb though
A lot of that shouts UB or compiler bug to me. I don't get this in my code unless there is some UB I missed. Unfortunately there are places where UB is unintuitive and may not even be present in newer versions of the language.
Not a fact. It's typical to have debug and release builds, and possibly other flavors.
Of course sometimes all you have is a stack trace from a release build, and then you need to debug that. But if you can, debug the debug build, it's much easier.
Frankly, that's stupid advice. Typically you have at least two build modes, debug and release. Debugging without optimization is easier because the source code maps to the compiler output, also a program without optimizations behaves the same as with optimizations, unless you put undefined behaviour into your code (should be a rare thing for an experienced programmer) or hit a compiler bug (also quite rare).
I'm not sure where you got these ideas, but there are tons of benefits to debug builds like catching out of bounds lookups on vectors the moment they happen and faster compilation.
It's bizarre that you don't realize everyone works this way.
Not when you want to debug it.
I think you're mistaking debug information not lining up with your program for different behavior, but these are not the same thing.
Crashes in production happen with optimized builds. You need to be able to inspect the core and figure out what happened from there, as usually you can't reproduce the scenario.
What about just compiling and running your program after you make a change or get a crash?
Crashes in production happen with optimized builds. You need to be able to inspect the core and figure out what happened from there, as usually you can't reproduce the scenario.
Right... What's your point? This scenario doesn't overlap with regular iterations. Normal workflow and a crash after a program is distributed are two separate things.
The crash when your program is distributed is the normal workflow. What matters is that your program runs flawlessly in its distributed environment, not that your test suite passes locally.
Testing is but a proxy to achieve the true goal, and is far from perfect.
Your normal workflow is only finding bugs once you've released your program to other people? You don't find any bugs while you work on it? You write a program and if it compiles you immediately assume everything is fine, release it and wait for someone to complain?
Do you realize that this thread was about someone saying that debug builds are a legacy holdover from the 80s ?
Testing is but a proxy to achieve the true goal, and is far from perfect.
What is it exactly that you think you're replying to? All this was about was someone thinking there was no use for debug builds. You're hallucinating some sort of discussion or argument about distributed software, services, updates, none of it is even coherent to what is being talked about.
Did you get mixed up and think that people saying that debug builds are crucial for iterations means that they were saying no one ever needs to debug an optimized build?
Postmortem debugging on production builds and without debug info is just harder (depends on how much postmortem info your bug report system provides, and at least on Windows it still makes sense to create a PDB file and archive that inhouse to associate that with the minidump you're
getting from the bug report, slightly mismatched debug info is still much better than no debug info at all). A production build crash doesn't mean that the symptoms are not reproducible on a debug build, and investigating the debug build after the bug has been reproduced is a lot more convenient.
Also a lot more bugs show up and are already fixed during development and never even make it to CI or even out into the wild. That's were debug builds and debuggers are most useful (during the initial development phase).
Sometimes I really have a feeling that software development is moving backward in time (shakes head). Debuggers are incredibly poweful tools, use them!
Doesn't change the fact it's completely unrealistic to expect that you can do that with a full debug build.
The industry has moved towards software as a service, and sometimes your service crashes and you need to figure out why.
Even if you want to turn the problem into a regression test that you can run a debug build against, you'll still need to look at the core of the optimized build to figure out what happened to begin with.
GDB behaves like any other debugger when it comes to optimized versus unoptimized builds. Debugging an optimized build is possible in any debugger, but your debugging information no longer maps exactly to compiler output, making source-level debugging harder.
Extremely bad advice. There is no point in debugging something that bears no relation to the software you release, and compiler optimizations is the only reason to use C or C++ in the first place.
It's extremely good advice. Debugging is all about simplifying things and finding the problem. Deal with your program without optimizations first. Once that is set, then you can deal with any differences due to optimizations, which should be extremely rare, because that would be a bug anyway.
Mixing two sources of complexity is extremely bad advice.
I miss the part of what a modern debug lacks.