C++11 backwards compatibility
Asked Answered
D

2

22

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.

Demetra answered 1/11, 2013 at 15:4 Comment(4)
There isn't any standard C++ ABI, so there isn't anything to break...Heterogamete
@Heterogamete so as long as I don't reference any symbols that would only exist in an up to date libstdc++, I should be fine?Demetra
@Roddy: There are non-standard ABIs and I imagine the question is about using different versions of libstdc++ in the same platform, so there is one ABI.Watchman
@BrianSchlenker: No, even using symbols that exist in a previous libstdc++ can break if the definition of those symbols change. For example, if you enable compliance of std::string the code will not be binary compatible with code that uses the old (now incorrect) implementation of std::string. My advice if you mean to target systems with older libstdc++ is to statically link your version into the binary --this still leaves the problem of shipping libraries...Watchman
I
13

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.
Incommunicado answered 1/11, 2013 at 20:2 Comment(3)
-1 Binary incompatibilities? Different definitions of data structures are hard to detect and lead to UB.Cabriole
You are correct: deprecated symbols/definitions can break code that expects the newer definitions; however, the question was about which new (C++11) features could be used with older libraries, not which old features still work in new libraries.Incommunicado
Features are irrelevant. Behaviour and memory layout are what really matters. To work with any given object a library that created it is required. See @David Rodriguez's comment.Cabriole
P
3

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.

Parrotfish answered 12/2, 2014 at 18:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.