C++ Insights – See your source code with the eyes of a compiler
github.com
github.com
It is also available at a touch of a button within the most excellent https://godbolt.org/
along side the button that takes your code sample to https://quick-bench.com/
Those sites and https://cppreference.com/ are what I'm using constantly while coding.
I recently discovered https://whitebox.systems/ It's a local app with a $69 one-time charge. And, it only really works with "C With Classes" style functions. But, it looks promising as another productivity boost.
The currently-available version is focused on a "write-based" workflow for C and a subset of C++: JIT-compiling, running and auto-debugging the function you're working on in the background whenever you edit it.
It shows a timeline of how the data in your function changes, with the intent being to give you feedback as immediately as possible.
We're currently working on a "read-focused" workflow, which is basically about making WhiteBox also work as a timeline debugger (for EXEs compiled from any language) with a few extra tricks up its sleeve...
Feel free to ask any questions either here or on our discord: https://chat.whitebox.systems
e.g. https://cppinsights.io/lnk?code=Ly8gaHR0cHM6Ly93d3cuc2NzLnN0...
Just open the drop-down to select the C++ standard. Below, there is a section "More Transformations". Enable "Show coroutine transformation", and you will get the transformation you're looking for: https://cppinsights.io/s/4d8c3fc1
Disclaimer: I'm the author.
Myself and my ancient h/w and s/w engineering friends have been having a discussion recently about how the modern C++ language features are generating code that is not readily debugged at the source level.
The compiler has always created assembly that implements the feature described by teh high level language, but histoirically these have had a relatively one-to-one relationship with the source code.
However in the world of post C++11 many more abstracted features are supported, and they no longer have any kind of relation to the source in terms of something you could inspect with a debugger (except in assembly).
So it seems a tool like this is really useful, but unfortunately almost inherently compiler specific.
Maybe GNU can port this to g++?
I miss the part of what a modern debug lacks.
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?
Check this link and the twitter posts linked there, other well known developers have this issue: https://developercommunity.visualstudio.com/t/std::move-and-...
# C++ stdlib
skip -gfi /home/trent/mambaforge/envs/td/x86_64-conda-linux-gnu/include/c++/10.3.0/\*
skip -gfi /home/trent/mambaforge/envs/td/x86_64-conda-linux-gnu/include/c++/10.3.0/*/*
skip -gfi /home/trent/mambaforge/envs/td/x86_64-conda-linux-gnu/include/c++/12.3.0/\*
skip -gfi /home/trent/mambaforge/envs/td/x86_64-conda-linux-gnu/include/c++/12.3.0/*/*
# tl::expected
skip -gfi /home/trent/.cache/cpm/expected/5acc53468c550d1f25ce819a675b60bfa0bbc69d/include/tl/\*
It's not perfect, but at least I don't have to step through annoying things like std::unique_ptr<Foo>.get() a million times whilst debugging.https://learn.microsoft.com/en-us/visualstudio/debugger/just...
Also, there are scenarios where debugging without optimizations isn't an option.
The issue with std::move has been solved for a while and was a VC++ bug, not C++.
https://devblogs.microsoft.com/visualstudio/a-year-of-cpp-im...
> 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++.
"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).
Just learn how to use gdb, it's quite capable.
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.
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.
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.
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.
Legacy cargo-cult holdover from the 1980's. No real reason for it today.
> also a program without optimizations behaves the same as with optimizations
Not when you want to debug it.
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.
Testing is but a proxy to achieve the true goal, and is far from perfect.
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 this supposed to mean?
Additionally most software runs as a service this day, so you have fast deployment iterations to collect errors.
Even for something like games, they get OTA updates all the time, fixing bugs that were only found while people were playing the game.
> What is this supposed to mean?
This is a pretty simple sentence in straightforward English. Which word do you have a problem with?
It argues that you shouldn't debug optimized builds.
Obviously, as I pointed out, a real programmer needs to be able to debug optimized builds.
Maybe you should be the one tracking what you're replying to.
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.
Mixing two sources of complexity is extremely bad advice.
I've found it maps orders of magnitude better than C++ under the same optimisation levels.
Since it's source-to-source, I don't think being based on clang actually matters for anything unless you happen to use GCC-specific extensions. I would also expect clang and gcc to behave similary when cutting through abstraction.
I'm not sure, but it also seems like the output code should be able to compile? Then you can probably use g++ for that step.
What specific features do you have in mind? I generally believe this is because DWARF and debuggers haven't been keeping up, not because of inherent limitations.
I'm happy to add an entry for Emacs once somebody develops a plugin for that editor.
Being able to cut through abstraction is very nice and quite important when you want to understand WHAT you are writing from the machine's perspective (or even in general when you don't know the abstraction yet). I love using Haskell, but have no idea what kind of machine code GHC spits out at the end (something based on the spineless tagless G-machine, an abstraction I barely understand by itself).
There is GHC's core, an indermediate representation of your code (mostly "just" desugared Haskell), which is comparable to Andreas' C++ Insights. Which you can get by passing `-ddump-simpl` with additional flags to disable displaying everything.
A list of other internal GHC data to dump is https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_gui...
But getting an idea what assembly is finally generated is still hard (at least for mé). Or, to rephrase, to know if "everything" is finally unpacked and strict or not, and if not: why not.
Btw. IMHO still the best book to read (of course not up-to-date, but to get the basic concepts of GHC) is https://www.microsoft.com/en-us/research/publication/the-imp... https://www.microsoft.com/en-us/research/uploads/prod/1987/0...
https://clang.llvm.org/docs/UsersManual.html#options-to-emit...
Gcc also has similar options
When you say the compiler explorer can do it, do you mean that it will 'inline' the output in a similar way to the assembly i.e. you can view the results 'within' the source code?