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