[HN Gopher] C++ Insights - See your source code with the eyes of...
___________________________________________________________________
C++ Insights - See your source code with the eyes of a compiler
Author : turrini
Score : 187 points
Date : 2024-04-05 23:15 UTC (23 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| johnea wrote:
| I wonder how helpful it is for g++?
|
| 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++?
| ColonelPhantom wrote:
| The readme indicates that it uses system headers (G++
| libstdc++) by default.
|
| 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.
| a1o wrote:
| Most of things that used to be g++ specific extensions are in
| standard nowadays. You can avoid by using a more recent c++
| version.
| pjmlp wrote:
| Not really, only a tiny couple of them.
| khuey wrote:
| > 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.
|
| 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.
| meindnoch wrote:
| What do you mean exactly? Like the inability of putting a
| breakpoint on the loop condition of a range-based for loop?
| pjmlp wrote:
| Pretty easy in VC++ debugger.
| pjmlp wrote:
| Even C doesn't map any longer when taking into consideration
| -O3, UB, vector units, and compiler replaced standard library
| calls.
|
| I miss the part of what a modern debug lacks.
| jstimpfle wrote:
| 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?
|
| Check this link and the twitter posts linked there, other
| well known developers have this issue:
| https://developercommunity.visualstudio.com/t/std::move-
| and-...
| pjmlp wrote:
| Use modern IDEs with features like Just My Code, which
| already help a lot.
|
| 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...
| jstimpfle wrote:
| 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++.
| pjmlp wrote:
| 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.
| jstimpfle wrote:
| 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).
| gpderetta wrote:
| [[gnu:: artificial]]
| jstimpfle wrote:
| cool!
| mgaunard wrote:
| You need to be able debug optimized builds. That's a
| requirement of the real world if you're a software
| engineer.
|
| Just learn how to use gdb, it's quite capable.
| JonChesterfield wrote:
| 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.
| otabdeveloper4 wrote:
| Just accept the fact that -O3 is the real compiler, and
| -O0 is the training wheels you might only use once or
| twice while learning to program.
| jstimpfle wrote:
| 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.
| flohofwoe wrote:
| 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).
| otabdeveloper4 wrote:
| > Typically you have at least two build modes, debug and
| release.
|
| 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.
| jstimpfle wrote:
| That's a really interesting mix of wild claims and plain
| wrong statements.
| jpc0 wrote:
| > 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.
| flohofwoe wrote:
| 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.
| otabdeveloper4 wrote:
| 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.
| CyberDildonics wrote:
| 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.
| flohofwoe wrote:
| Optimizations usually don't change the behaviour of a
| program (unless you hit UB, but that's what UBSan is
| for).
| trentnelson wrote:
| This has made stepping through C++ in gdb slightly less
| painful for me: use gdb's skip command. E.g., in my
| ~/.gdbinit: # 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/5acc53468c550d1f2
| 5ce819a675b60bfa0bbc69d/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.
| lelanthran wrote:
| > Even C doesn't map any longer when taking into
| consideration -O3, UB, vector units, and compiler replaced
| standard library calls.
|
| I've found it maps orders of magnitude better than C++ under
| the same optimisation levels.
| nurettin wrote:
| Sounds like a huge undertaking, but why not use clang for
| introspection and gcc for compiling? It is still useful.
| ColonelPhantom wrote:
| Honestly, from the title, I expected something that gave actual
| 'insights' into the compiler, rather than the code. For example,
| indicating applied and potential (missed) optimizations. But
| seeing what it was, I was definitely not unpleasantly surprised
| :)
|
| 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).
| jaredwy wrote:
| compiler explorer/clang can do this.
|
| https://clang.llvm.org/docs/UsersManual.html#options-to-emit...
|
| Gcc also has similar options
| ColonelPhantom wrote:
| Ooh nice, I completely forgot that that existed.
|
| 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?
| linhns wrote:
| I think Haskell creators never meant to have users care about
| those abstractions. It's more about what, not how, and given
| its terseness and power, I'd be happy to be a normal user.
| ReleaseCandidat wrote:
| > I love using Haskell, but have no idea what kind of machine
| code GHC spits out at the end
|
| 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 me). 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...
| pkkm wrote:
| Yeah, I like this, but the tool I wish existed the most is some
| kind of pointer aliasing checker. Something that would tell me
| when I've violated strict aliasing or, conversely, when I've
| forgotten to put in a _restrict_ and now the compiler is
| reloading things from memory unnecessarily.
| corysama wrote:
| C++ Insights is available online at https://cppinsights.io/
|
| 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.
| donadigo wrote:
| I'll add to that my own Visual Studio extension that improves
| runtime debugging by showing you which lines are actively
| executing and what changes happened line-by-line:
| https://d-0.dev It integrates with the VS debugger completely
| and does not require any changes to one's codebase. It's also
| available on the marketplace if you want to try it out:
| https://marketplace.visualstudio.com/items?itemName=donadigo...
| yukIttEft wrote:
| I _wish_ there was a way to show the code that is generated when
| using co_return or co_await
|
| e.g.
| https://cppinsights.io/lnk?code=Ly8gaHR0cHM6Ly93d3cuc2NzLnN0...
| andreasfertig wrote:
| Sometimes, wishes come true!
|
| 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.
| yukIttEft wrote:
| This is very helpful, thx.
| nurettin wrote:
| It looks like a perfect candidate for a vs code extension.
| dailykoder wrote:
| I use neovim btw
| andreasfertig wrote:
| Thanks to another contributor there is a vim extensions:
| https://github.com/Freed-Wu/cppinsights.vim
| gpderetta wrote:
| Now do Emacs. 2 minutes od searching didn't hit anything :)
| andreasfertig wrote:
| Sorry, I don't know about an Emacs plugin. All the
| plugins/extensions I'm aware of are listed in the
| Readme.md:
| https://github.com/andreasfertig/cppinsights/#c-insights
| --vi...
|
| I'm happy to add an entry for Emacs once somebody
| develops a plugin for that editor.
| andreasfertig wrote:
| Thanks to a contributor there is such an extension:
| https://marketplace.visualstudio.com/items?itemName=devtbi.v...
___________________________________________________________________
(page generated 2024-04-06 23:02 UTC)