Demangling C++ Symbols in Rust
fitzgeraldnick.com
fitzgeraldnick.com
Then, later:
Additionally, I’ve been running American Fuzzy Lop (with afl.rs) on cpp_demangle overnight. It found a panic involving unhandled integer overflow, which I fixed. Since then, AFL hasn’t triggered any panics, and its never been able to find a crash (thanks Rust!) so I think cpp_demangle is fairly solid and robust.
That's what I like to see. Targeted useful reimplementations in Rust that play well to its strengths. In this case, as a double benefit to both the Rust ecosystem and to anyone that wants a robust demangling library.
Switching languages is cool, but the Rust code is actually longer and still uses a hand written parser, so how can you be sure it is any more correct or won't eat all your memory?
[0] http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_...
[1] http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/fuzz/cxa...
[2] http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/tes...
However, an even more important question is how many exploitable bugs remain in the LLVM library vs the Rust library. The data suggests that the answer for Rust is zero but the answer for LLVM is greater than zero.
Well, it's been fuzzed, so there's a pretty decent chance that the LLVM code has zero exploitable flaws. Also, the C++ demangler isn't as security-sensitive as many other more important projects.
That said, as a general rule raw C-style string parsing, which that C++ code is an example of, is asking for trouble. It's painful to write, painful to maintain, painful to debug, and, when it fails, fails in the worst possible way. In my opinion there's little benefit to using C++ for these workloads.
AFAIK Valgrind can catch many memory access related errors. And static analyzers can point out where such errors could happen.
From a different perspective: Why don't people do pascal stile strings with C or C++ (and such) ? I think even i could make a library that does all the string.h things but with length-prefixed strings. People have been complaining for years now about C stile strings (that have been widely used for decades now). But nobody ever did anything about it ?
PS I, myself, don't find it "painful" to use C stile strings. A few basic precautions (like using strncmp(bla,blaa,buffer_size)) and your fine. Off-by-one is more of a problem, at least for me at night (valgrind and llvm static analyzer point even those out).
True, but Valgrind doesn't exist in every OS that one might need to work with, specially embedded ones, and according to Herb's talk at CppCon 2015, only 1% of the audience was using any form of static analyisis tooling.
The world of C and C++ programming, in typical 9-5 enterprise jobs is quite different from HN ideals about code quality.
> I think even i could make a library that does all the string.h things but with length-prefixed strings. People have been complaining for years now about C stile strings (that have been widely used for decades now). But nobody ever did anything about it ?
Because it takes a big effort to make such library part of ANSI C.
> PS I, myself, don't find it "painful" to use C stile strings. A few basic precautions (like using strncmp(bla,blaa,buffer_size)) and your fine.
You already did a possible security exploit on your example, as you need to guarantee 100% of the time that bla and blaa sizes are always less or equal than buffer_size.
When working with a team it suffices that another person changes your code without accounting for this invariant.
bla and blaa buffer sizes, yes. I mostly string file names/paths, that have NAME_MAX and PATH_MAX. So my excuse here is that all my buffers have the same size (not the best excuse, i know). PS I always sanitize on input if the input can be anything (network/ipc sockets, for example).
>True, but Valgrind doesn't exist in every OS that one might need to work with, specially embedded ones, and according to Herb's talk at CppCon 2015, only 1% of the audience was using any form of static analyisis tooling.
Quick google shows some tools for windows. I don't know how good they are. Clangs static analyzer seems to work on windows, for static analysis. But if it compiles on linux/bsd/osx then people should check before shipping the code.
This just reminded me of the latest Linus rant[0].
Then there is fuzzing and formal verification, that are too much for "normal" programs (these are not C specific).
>The world of C and C++ programming, in typical 9-5 enterprise jobs is quite different from HN ideals about code quality.
As is in the world of hobby C and C++ programming. And python, and ruby, and haskell, and... It just shows more in C. But C is still the king when it comes to portable and efficient programs, and that won't change soon (although there is less need for such programs, as "embedded" today equals "has only 512MB RAM").
[0] http://lkml.iu.edu/hypermail/linux/kernel/1702.2/05171.html
People have been complaining for years now about C stile strings (that have been widely used for decades now). But nobody ever did anything about it ?
There have been many efforts (http://www.and.org/vstr/comparison), but ultimately they all failed to find widespread adoption because they're solving the wrong problem.For any non-trivial data munging operation experienced C programmers quickly ditch C strings in favor of vectors. The simplest approach employs a simple pointer and length (or boundary) tuple; i.e. a vector. You can get fancy by wrapping them in a struct, but even that isn't necessary and, especially wrt API design, often needlessly forces interface users to create temporary "slice" objects with an annoying type peculiar to the interface. Newer languages offer nicer interfaces for slices, but simple pointers are hard to beat in terms of simplicity and usability. (The only problem with simple pointer derivation and manipulation a la C is that they're difficult for a compiler to both verify the correct use of _and_ to aggressively optimize. You must choose one or the other. Requiring the user to use specialized, compiler sanctioned primitive aggregate types in languages like Rust is a way to meet the compiler half-way.)
Also, for complex parsing tasks experienced C programmers will often code a straight-up state machine, or leverage a parser generator. In both cases C-style NUL terminated strings aren't even visible in the rearview mirror.
IME, I've found that parsing of data is one of the areas where C excels. And by parsing I don't mean attacking data with regular expressions. Likewise, for creating complex data structures like graphs C excels, especially when you want to employ intrusive data structure patterns for efficiency and clarity. Pointers are wonderful abstractions that way.
There are a lot of difficulties with C, particularly regarding memory management. But string processing is not one of them, except for programmers for whom at that moment parsing is synonymous with crude hacks using regular expressions or the limited interfaces for C-style strings. It's self-inflicted. The solution doesn't require a complex framework. Addressing the issue merely requires reframing the task. Fortunately, when reframing is too burdensome, for quick and dirty string hacking there are plenty of alternative languages.
Let's not go overboard. Claiming the number of bugs is zero in any non-trivial piece of software is generally a losing proposition, no matter the language.
That said, I think I know what you're trying to express, and I would say it like this: The number of bugs in a program written in Rust compared to C or C++ should be statistically less, all other things being equal. Certain classes of bugs are impossible with Rust at best, and easier to locate or isolate at worst (assuming you haven't wrapped the entire program in one giant unsafe block).
Not that I'm actually advocating for that at this point. This is a new library, and as stated in the blog still has some differences in output compared to other similar libraries.
$ nm /usr/lib/libc++abi.dylib | grep cxa_demangle
00000000000018e0 T ___cxa_demangle
Which means you can compile the following c++ file with clang++ and gets demangling from the system: #include <iostream>
extern "C" char *__cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status);
int main() {
std::cout << "Demangled: " << __cxa_demangle("_Z17GetExecutablePathPKcb", nullptr, nullptr, nullptr) << "\n";
}
We need a great demangler in LLVM because we're using it in the LLDB debugger for instance. The LLVM one is quite slow actually, if anyone is interested in writing a (clean) very performant C++ one within LLVM, I'm volunteering to help the review and integration :)(edit: formatting)
Fair enough, that makes sense. If you are aiming to be a full toolchain, it's useful to have it in-project.
Edit: Whoops! s/fool/full/
Would it be possible to translate the Rust code into C++ and thus basically get the Rust safety in C++?
_ZN2js18CompartmentChecker5checkIN2JS8GCVectorI4jsidLm0ENS_15TempAllocPolicyEEEEEN7mozilla8EnableIfIXsrNS7_6IsSameIDTclptcvPT_LDn0E5beginEEDTclptcvSB_LDn0E3endEEEE5valueEvE4TypeERKSA_
coming from
template <typename Container>
typename mozilla::EnableIf<
mozilla::IsSame<
decltype(((Container*)nullptr)->begin()),
decltype(((Container*)nullptr)->end())
>::value
>::Type
check(const Container& container) { ... }I tried with 2.27.51 (Debian), and it works:
mozilla::EnableIf<mozilla::IsSame<decltype ((((JS::GCVector<jsid, 0ul, js::TempAllocPolicy>*)((decltype(nullptr))0))->begin)()), decltype ((((JS::GCVector<jsid, 0ul, js::TempAllocPolicy>*)((decltype(nullptr))0))->end)())>::value, void>::Type js::CompartmentChecker::check<JS::GCVector<jsid, 0ul, js::TempAllocPolicy> >(JS::GCVector<jsid, 0ul, js::TempAllocPolicy> const&)This is only true of UNIX system linkers, before the FOSS and UNIX clones wave, it was common for each compiler to have its own language specific linker.
Not that I have a use case in mind or anything, just curious.
Gross! I wonder what that's for. Somebody's hack to allow same-name/same-interface header inline functions to coexist?
You stay classy, Microsoft.
> Its not just the grammar that’s huge, the symbols themselves are too. Here is a pretty big mangled C++ symbol from SpiderMonkey [...] That’s 355 bytes!
Here's a >4kB symbol I encountered while liberating some ebooks from an abandoned DRM app:
tetraphilia::transient_ptrs<tetraphilia::imaging_model::PixelProducer<T3AppTraits> >::ptr_type tetraphilia::imaging_model::MakeIdealPixelProducer<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 0ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> > > >, tetraphilia::Terminal> >, T3AppTraits, tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, tetraphilia::imaging_model::SeparableOperation<tetraphilia::imaging_model::ClipOperation<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > > >(tetraphilia::ArgType<tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 0ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> > > >, tetraphilia::Terminal> > > >, T3AppTraits::context_type&, tetraphilia::imaging_model::Constraints<T3AppTraits> const&, tetraphilia::imaging_model::SeparableOperation<tetraphilia::imaging_model::ClipOperation<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > >, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::SegmentFactory<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >*)I believe Microsoft's mangling scheme is actually older than gcc's current one. While gcc changed its name mangling everywhere to a new one based on Intel's IA-64 ABI, MSVC probably kept its own unchanged from compiler release to compiler release. I don't recall the reason for gcc changing its name mangling; perhaps better standard compliance?
IIRC, the MSVC scheme has an annoying property, in that "class foo" and "struct foo" have different mangling, while they're supposed to be completely interchangeable according to the C++ standard (other than the default access being "private" for class and "public" for struct).
_ZN5boost6detail7variant15visitation_implIN4mpl_4int_ILi40EEENS1_20visitation_impl_stepINS_3mpl6v_iterINS7_6v_itemI25SelectedEntityChangedDataNS9_IN11InputAction17ServerCommandDataENS9_INSB_18SetupBlueprintDataENS9_INSB_13BuildRailDataENS9_I2IDI20CustomInputPrototypetENS9_IN10ActionData22TrainWaitConditionDataENS9_INSI_18TrainWaitConditionENS9_INSB_22BuildTerrainParametersENS9_I27DeciderCombinatorParametersNS9_I30ArithmeticCombinatorParametersNS9_INSB_18PlayerJoinGameDataENS9_INSB_7CrcDataENS9_INSB_20SetBlueprintIconDataENS9_I20AbilitySpecificationNS9_INSB_17TakeEquipmentDataENS9_INSB_18PlaceEquipmentDataENS9_I6VectorNS9_IdNS9_ISF_I9ItemGrouphENS9_INSB_15MarketOfferDataENS9_ISsNS9_INSI_33BehaviorModeOfOperationParametersENS9_INSI_17TrainScheduleDataENS9_INSB_18GuiTextChangedDataENS9_INSB_14GuiChangedDataENS9_INSB_12GuiClickDataENS9_INSB_20SelectItemParametersENS9_INSI_24LogisticFilterSignalDataENS9_INSI_22LogisticFilterItemDataENS9_ISF_I19TechnologyPrototypetENS9_INSI_10SignalDataENS9_INSI_26CircuitConditionParametersENS9_INSB_19SetFilterParametersENS9_INSB_19BuildItemParametersENS9_INSB_16CancelCraftOrderENS9_INSB_9CraftDataENS9_I13ShootingStateNS9_IhNS9_ItNS9_IjNS9_IbNS9_ISF_I13ItemPrototypetENS9_ISF_I15RecipePrototypetENS9_I28ItemStackTargetSpecificationNS9_I11RidingStateNS9_I9DirectionNS9_INSB_14SelectAreaDataENS9_I12RealPositionNS7_7vector0INS3_2naEEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELl40EEENS8_IS32_Ll48EEEEENS1_14invoke_visitorINS1_11get_visitorIKS10_EEEEPKvNS_7variantINS1_13over_sequenceINS7_8vector48IS1N_S1M_S1L_S1K_S1J_S1I_S1G_bjthS1E_S1D_S1C_S1B_S1A_S19_S18_S17_S15_S14_S13_S12_S11_S10_SZ_SY_SsSX_SW_dSU_ST_SS_SR_SQ_SP_SO_SN_SM_SL_SK_SJ_SH_SE_SD_SC_SA_EEEEJEE18has_fallback_type_EEENT1_11result_typeEiiRS3K_T2_NS3_5bool_ILb0EEET3_PT_PT0_
The c++filt output is 13,776 characters, so I can't easily copy it here.Boost Lambda (unstripped): 44176 bytes
Boost Lambda (stripped): 18808 bytes
C++11 Lambda (unstripped): 24896 bytes
C++11 Lambda (stripped): 14712 bytes
Test program is pretty simple:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
using namespace boost::lambda;
int main(int, const char**)
{
std::vector<int> v;
for (int i = 0; i < 100; ++i)
v.push_back(i);
//std::for_each(std::begin(v), std::end(v), std::cout << _1 << constant('\n'));
std::for_each(std::begin(v), std::end(v), [](int i) { std::cout << i << '\n'; });
return 0;
}
I'm using Boost 1.58.0 and GCC 5.4.0 with -std=c++1y flag only to get the numbers above.(edit: formatting)
Scrolling the quoted symbol on mobile was one of the most hilarious moments I had on HN. Thanks.
> You stay classy, Microsoft.
This is only true on the HN universe of clang, gcc and MSVC++ trio.
Out there in the real world, there are plenty of C++ compilers being used.
https://en.wikipedia.org/wiki/List_of_compilers#C.2B.2B_comp...
I'd argue that it has to do with backwards compatibility, but every version of MSVC breaks binary compatibility anyway.