This is a very uninformed question, but:
I would like to start using C++11. Can I continue to use my large collection of libraries which were compiled with my old gcc 4.2.1 compiler or do I need to recompile them all with a new compiler? I would think (or hope) the answer is no, but I am only a dabbler.
So that I may have at least part of my ignorance removed, can you explain why in either case?
Thanks
Yes, you should.
The weaker reason is not binary compatibility, the problem is about expectations. A C++11 enabled compiler will expect a number of features to be available (move constructors among them) and use them when appropriate. And that's only scratching the tip of the iceberg, there are several other incompatibilities (auto, 0 and its interaction with pointers, ...).
It means that any inline method in a header may suddenly be interpreted differently, in light of the C++11 Standard.
The stronger reason is that each version of the compiler comes with its own Standard Library implementation. You don't really want start mixing various versions around and especially not when they have undergone such major changes (once again, rvalue references...).
Believe me, it's simpler to recompile now rather than having that nagging thought that each bug that appear may be due to an incompatibility between old and new libraries...
It's a compiler question. For instance, if you have a single compiler which supports both C++03 and C++11 depending on a compiler switch, you can very likely mix libraries. There's nothing new in C++11 that forces an incompatibility with C++03.
Howeve, you mentioned that your libraries were compiled with GGC 4.2.1. Since C++11 was just an idea back then, it's quite likely that GCC back then was implemented in ways that turned out to be incompatible with C++11.
For instance, std::list::size() must be O(1) in C++11, but it could be O(N) in C++03. GCC chose a O(N) implementation back then, not knowing the future requirements. The current GCC std::list::size implementation is compatible with both C++11 and C++03, since O(1) is better than O(N).
The answer totally depends on the API of your library and its implementation dependencies.
The conditions that guarantee that you don't need to recompile are:
-- Your library doesn't use C++ specific features in its public API.
That implies:
Your library doesn't provide classes/class-templates/function-templates/other C++ specific stuff.
You don't accept/return C++ classes to/from your library functions.
You don't pass function parameters by reference.
You don't provide public inline functions with C++ specific implementations.
You don't throw exceptions from your functions.
You don't (because you have no reason to) include C++ specific library headers in your public headers. (It wouldn't hurt if you do include them but everything must be OK if you remove such includes. It is like an indicator.)
-- Your library depends only on the libraries that binary-compatible with those available in your new build environment.
If those conditions are not satisfied then there is no guarantee that your library will work correctly. In most cases it is much easier to recompile than to make sure that everything works correctly.
Either way if you are going to make binary compatible API that satisfies the conditions above then it is much better to design and implement C language API. This way you automatically satisfy the above conditions and don't fall into sin of writing C-style C++ code.
You can use large parts of C++11 without recompiling (assuming ABI compatability), but a particular important part, for me atleast, will not be accessible to the already compiled code - move semantics.
Move semantics can make your code faster just by recompiling with a C++11 compiler (and preferably, a C++11 stdlib).
There are also other reasons. Maybe your preferred library has become C++11 aware since you last compiled it, and is now more efficient, safer or easier to use if compiled with a C++11 compiler?
For your own libraries, with C++11 you surely can make it them more efficient, safer and easier to use? :)
If your interfaces to the compiled code uses any template which was modified by C++11, then yes, you have to recompile. Otherwise you probably can continue to use your old libraries (unless the compiler provider also decided to make changes of the ABI at the same time, because it's a great opportunity to fix long-standing ABI bugs which are otherwise often refrained from fixing because of binary incompatibilities).
Related
This Github repository added std::regex to the list of regular expression engines and got decimated by the others.
Why is that std::regex - as implemented in libstdc++ - so much slower than others? Is that because of the C++ standard requirements or it is just that that particular implementation is not very well optimized?
Also in the shootout std::regex was unable to compile several regular expressions that all the others accepted, even after adding the flag std::regex::extended. They were (?i)Twain, \b\w+nn\b, (?i)Tom|Sawyer|Huckleberry|Finn, \s[a-zA-Z]{0,12}ing\s, ([A-Za-z]awyer|[A-Za-z]inn)\s and \p{Sm}.
UPDATE: Added comparison with boost::regex.
UPDATE2: added ctre
Is that because of the C++ standard requirements or it is just that that particular implementation is not very well optimized?
The answer is yes. Kinda.
There is no question that libstdc++'s implementation of <regex> is not well optimized. But there is more to it than that. It's not that the standard requirements inhibit optimizations so much as the standard requirements inhibit changes.
The regex library is defined through a bunch of templates. This allows people to choose between char and wchar_t, which is in theory good. But there's a catch.
Template libraries are used by copy-and-pasting the code directly into the code compiling against those libraries. Because of how templates get included, even types that nobody outside of the template library knows about are effectively part of the library's ABI. If you change them, two libraries compiled against different versions of the standard library cannot work with each other. And because the template parameter for regex is its character type, those implementation details touch basically everything about the implementation.
The minute libstdc++ (and other standard library implementations) started shipping an implementation of C++ regular expressions, they bound themselves to a specific implementation that could not be changed in a way that impacted the ABI of the library. And while they could cause another ABI break to fix it, standard library implementers don't like breaking ABI because people don't upgrade to standard libraries that break their code.
When C++11 forbade basic_string copy-on-write implementations, libstdc++ had an ABI problem. Their COW string was widely used, and changing it would make code that compiled against the new one break when used with code compiled against the old one. It took years before libstdc++ bit the bullet and actually implemented C++11 strings.
If Regex had been defined without templates, implementations could use traditional mechanisms to hide implementation details. The ABI for the interface to external code could be fixed and unchanging, with only the implementation of the functions behind that ABI changing from version to version.
From the manual:
In the GCC 5.1 release libstdc++ introduced a new library ABI that includes new implementations of std::string and std::list. These changes were necessary to conform to the 2011 C++ standard which forbids Copy-On-Write strings and requires lists to keep track of their size.
It is possible to use the _GLIBCXX_USE_CXX11_ABI macro to control whter the library headers use the old or the new ABI, independently of which "-std" is being used.
I'd like to know what the implications of using this "compatibility ABI" would be? I guess that the run-time performance of small-string operations will be impacted (negatively I assume), and that list-size access goes from O(1) (C11 ABI) to O(N) (compatibility ABI).
Are my guesses correct and can anyone elaborate?
Are there other implications which I have missed? What about atomics and concurrency features? Any impact?
Your first question is actually answered by the manual itself:
... the choice of ABI to use is independent of the -std option used to
compile your code... This ensures that the -std does not change the ABI, so that it is
straightforward to link C++03 and C++11 code together.
Regarding the second question, I'm afraid it's hard to generalize the impact because it depends on how your code is using the standard library. Does it copy strings a lot? How often a list size is queried? Is the code multi-threaded?
Although atomics and concurrency were introduced in C++11's standard, I'd guess that stdlib++ copy-on-write mechanism already used a variation of it anyhow. Those implementations are typically thread-safe.
Perhaps one thing you didn't directly mention is the impact on other std components that depend on those behaviors, such as list::splice
As a downstream maintainer in a Linux distribution, some of the packages that I usually maintain are starting to use the C++11 features in their code base. All of them depend on different libraries packaged by the Linux distributions.
Problems with the ABI could appear when mixing C++11 code with C++98 and AFAIK, most of the current major Linux Distributions are not enabling the C++11 flag by default when compiling software to generate packages.
The question is: How are the major Linux distributions handling the entry of C++11 code? Is there a decent way of checking or avoiding these problems with the ABI when using system libraries?
Thanks.
The issue has nothing to do with C++11 vs C++98 except that C++11 can motivate binary changes. There is nothing special about binary changes motivated by C++11. They are just as breaking or non-breaking as regular binary changes. Furthermore, they are only changed if the library maintainer specifically chooses to change his binary interface.
In other words, this has nothing to do with the Standard version and everything to do with the library, unless the library explicitly chooses to offer two different binary interfaces to different Standard versions (which is still a library choice). Excepting this case, you are just as broken in C++98 as you are in C++11. Itanium is backwards compatible between the C++11-supporting versions and the C++98-supporting versions, so the compiler ABIs are not broken.
From memory, unless you're using 4.7.0 which they broke for fun and then unbroke, you're pretty much safe with libstdc++- they are storing up ABI breakage for a future release when they can make one big break.
In other words, whilst the transition period to C++11 can introduce additional motivation to break ABI and therefore additional risk, actually using C++11 itself does not introduce any additional risk.
Is there anything from c++11 that I can use and expect compiled binaries to run on older systems? How can I tell which parts of c++11 are a part of the libstdc++.so and what actually gets compiled into the binary? Maybe I don't fully understand how such things work. Does c++11 break ABI compliance with older libraries?
An example for clarity:
Say I compile a program that uses auto and the new range based for loop. These things seem like they should work on systems with old c++ runtimes because they break down into c++ that would be valid on those machines. However, using something like regex should break on older systems because it won't be in their runtime.
I haven't tested my theory yet because I don't have access to a c++11 compatible compiler, and my google searches haven't been helpful.
You are correct. The code itself compiles to work on any platform with a C++ compiler. The new language constructs (ranged for, new keywords like auto, etc.) compile with a new compiler to work just fine on older systems.
However, if you try to link code that uses new symbols (like regex) to an old library, then you run into problems, no matter whether you link statically or dynamically, because the old library does not have the new symbols.
Assuming your code uses new symbols:
If you statically link to an old library, the linkage will fail because the new symbols do not exist in the old library.
If you dynamically link to an old library, you should still get linker problems, again because the library does not contain the new symbols.
If you statically link to a new library, the resulting binary will work on an older system.
If you dynamically link to a new library, the resulting binary will work on an older system if it already has the new library or if you distribute the new library with your binary.
But if you then try to replace the new dynamic library with an old dynamic library, it will not be able to link to the new symbols in that library, again because they aren't there.
The standard does not make any guarantees about anything working with earlier implementations. The specification defines requirements on an implementation and an implementation either conforms to those requirements or it does not. Splicing together parts of a C++11 implementation with parts of an earlier implementation is not portable and it's unlikely to be practically possible.
It's possible even that writing a program which does not use the standard library at all and which does not use any C++11 features will not be ABI compatible with binaries from a C++03 implementation. For example an implementer could potentially take advantage of the new version to change calling conventions. So in general limiting a program to features like auto and range-for will not necessarily be ABI compatible.
How can I tell which parts of c++11 are a part of the libstdc++.so and what actually gets compiled into the binary?
Even if you do not use any part of the standard library (you can guarantee this by simply not using any headers) this does not guarantee that a compiled binary does not require run-time support provided by a C++11 implementation. A couple of examples of language features that may rely on run-time support are exceptions and virtual members.
And again, run-time library support isn't the only thing that could be ABI incompatible between C++03 and C++11.
Does c++11 break ABI compliance with older libraries?
No, I don't think the spec requires anything that prevents C++03 and C++11 implementations from sharing an ABI. However what you want to know is, are older specs sufficiently strict that older implementations must have an ABI that can potentially be shared by a C++11 implementation as well? The answer there is no as well and thus an implementer may be forced to break ABI compatibility when implementing C++11.
A specific C++03 and C++11 implementation may together make certain guarantees about mixing a C++11 compiled binary with C++03 run-time support, so you may be able to make use of that. I don't know of any such implementations, however.
Another option is that, rather than trying to mix C++11 and C++03 implementations, your C++11 implementation may be able to create self-contained binaries (or mostly self-contained, rather, since at the very least it would have to rely on the operating system's system call ABI) that don't require external run-time support.
The compatibility you can rely on is source level. You can write C++11 programs that also compile as C++03, and C++03 programs that also compile C++11, though of course with this method you're limited to the lowest common denominator between C++03 and C++11 and about the only C++11 feature you'll be able to benefit from would be move semantics.
I read that MSVC is not fully compilant to the ISO C++ standard (German Wikipedia and several Tech sites).
In which ways isn't C++ standards compilant?
Actually no compiler is fully standard compliant, but MSVC gained its reputation for implementing everything that the standard didn't explicitly state in a profoundly stupid and unportable way.
I would say that the latest releases are relatively good when it comes to standard support, at least when you try to compile standard compliant code in MSVC.
But MSVC is still very lazy when it comes to pointing out code, that doesn't follow C++ standard (even on the strictest settings), so porting code from MSVC to anything else is always huge pain.
But there are still many flaws/bugs/etc... for example unlike GCC, MSVC will allow you to modify a set/map iterator.
Well, I think it depends on your definition of compliant. There are several things that have not been implemented in the standard by almost any compiler company (several suggestion from the 98ish revision and template definitions in implementation files). MS has extended the language somewhat also. However, if you write code in basic c++ without the MS extensions or libraries, it will most likely be portable to another compiler with very, very minimal work (if any).
It's been a while since I've looked into this, but the C++ library that I work on uses quite a lot of template metaprogramming (nothing horribly complicated, but still beyond the simplest levels), and for quite a while it wouldn't compile under MSVC due to bugs or missing functionality in their template resolution code, although it works fine in GCC and Intel's C++ compiler.
I don't think we've tried it in the latest couple of revisions of MSVC, so they may have fixed those bugs.
Also, IIRC, MSVC does not turn on run-time type information support by default (for performance reasons), and support for that is required by the C++ standard.