17

I know that in principle this is probably undefined behaviour, but in the interest of dealing with a large project, here's my question about GCC:

Suppose I compile one transation unit with gcc -std=c++98, and another with -std=c++11, using the exact same compiler installation. Is there any sort of guarantee that I can link the two object files and obtain a well-defined program?

As far as I can tell, the potential problems can only come from different views of the library headers due to differing macros, and those in turn would at best add new member functions, but never member objects, to the standard library classes.

Would this somehow make it acceptable to compile different parts of a larger project with different language dialect options?

Update: I should add an orthogonal question: What about using two different versions of GCC (say 4.3 and 4.6), but wht the same dialect option (-std=c++98)? The listing in this GCC documentation seems to suggest that the library is compatible in both directions between 4.2.2 and 4.6.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084

3 Answers3

9

A priori, no. The safest solution is to assume that all of the compiler options are identical, except when the compiler specifically documents that the option doesn't affect binary compatibility. (Documentation which is sorely lacking in most compilers.) In practice, in the lack of documentation, it seems a safe bet that options which control warnings (-W... in g++) won't affect binary compatibility, and that options which affect code generation (language level, etc.) might: g++ generally maintains compatibility across different levels of optimization, where as VC++ doesn't.

Another real problem is defining preprocessor symbols in the command line. Again, the safest bet is that all of the defines be identical, but also again, some common sense is in order: one can hardly expect the standard library to have been compiled with preprocessor symbols which are used in your project (things like MYPROG_CONFIG_FILE_LOCATION, say). On the other hand, be aware that preprocessor definitions of _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC will affect binary compatibility (although g++ ensures that you will get a library version which works with them if you use them consistently).

With regards to your question: I would not expect to much impact on binary compatibility due to standard version, but it would hardly surprise me if the choice affects some pre-defined preprocessor symbols, in a way that would break binary compatibility in the library, much as if you'd compiled some of the modules with _GLIBCXX_DEBUG, and some without. It might work, but I wouldn't count on it.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 1
    "one can hardly expect the standard library to have been compiled with preprocessor symbols which are used in your project" -- and even if it was, and suppose for a moment that the macro `MYPROG_CONFIG_FILE_LOCATION` is used in `memset.c`, then the meaning of that define to `memset.c` is totally unrelated to its meaning in your program. So if compiling `memset.c` with/without `MYPROG_CONFIG_FILE_LOCATION` makes a difference to binary compatibility, then it will do so independently of whether your program happens to also use `MYPROG_CONFIG_FILE_LOCATION`. – Steve Jessop May 23 '12 at 11:27
  • @SteveJessop Yes. Even if it was, it should be transparent to you. In practice, all of the preprocessor symbols in your namespace (i.e. not starting with an underscore, and not containing two adjacent underscores) _should_ be safe. Preprocessor symbols in the implementation namespace, like `_GLIBCXX_DEBUG`, won't be. – James Kanze May 23 '12 at 11:40
3

I know that in principle this is probably undefined behaviour,

It's not.

Suppose I compile one transation unit with gcc -std=c++98, and another with -std=c++11, using the exact same compiler installation. Is there any sort of guarantee that I can link the two object files and obtain a well-defined program?

Yes, this is supported and works (there are exceptions, like enabling Debug Mode in one object and not the other, or using explicitly-ABI-changing options like -fshort-enums in one and not the other, but that should be obvious because that won't work even if you use the same -std option for both objects).

As far as I can tell, the potential problems can only come from different views of the library headers due to differing macros, and those in turn would at best add new member functions, but never member objects, to the standard library classes.

Right.

Would this somehow make it acceptable to compile different parts of a larger project with different language dialect options?

For GCC, yes, absolutely. As proof it's OK, consider that libstdc++.so itself contains some objects built with -std=c++98 and some built with -std=c++14.

Update: I should add an orthogonal question: What about using two different versions of GCC (say 4.3 and 4.6), but wht the same dialect option (-std=c++98)? The listing in this GCC documentation seems to suggest that the library is compatible in both directions between 4.2.2 and 4.6.

Not in both directions, you would need to use the libstdc++.so from GCC 4.6 (or newer), because the object compiled with that version might depend on symbols that were introduced in the newer version and are not present in the older libstdc++.so library.

Some related info at https://stackoverflow.com/a/49119902/981959

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
0

Language ABI is the same, but STL ABI is different. See https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

So do not recommend mixing libraries compiled with -std=c++98 -std=c++11. You may get crashes when passing data across image boundaries.

(It may work if you only call extern "C" functions and pass only PODs).

Also see related: Mixing different C++ standards with GCC

Chintan
  • 374
  • 2
  • 9