I recently spent a fairly substantial amount of time tracking down a problem that turned out to be caused by compiling a library with -D_GLIBCXX_DEBUG
(which tells libstdc++ to use a debug version of the standard library with extra checks) but compiling the client program without. This caused an ABI compatibility problem.
Is there some way I can automatically detect problems like this with GCC? Visual Studio provides the detect_mismatch
pragma which I think would have served this purpose, but I'm unaware of any GCC equivalent. GCC does something with embedding a symbol name (e.g. GLIBCXX_3.4.9
), and I can imagine schemes that would cause a linking error because of an undefined symbol if a corresponding symbol (e.g. mylib_debug_stl
) were not present, but the only ways I can think of to get a use of that symbol are really hacky.
Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?
clang, modulo bugs, is fully C++ ABI compatible with GCC (they both follow the intervendor Itanium ABI) on unix systems. Make sure you use the same standard library for all components because libstdc++ and libc++ are different implementations with completely different object layouts.
ABI break happens when one binary, e.g. shared object, uses a different ABI when calling functions on another shared object. If both binaries are not ABI compatible, the interpretation of the bytes would be wrong.
These details are defined as the compiler Application Binary Interface, or ABI. From GCC version 3 onwards the GNU C++ compiler uses an industry-standard C++ ABI, the Itanium C++ ABI. The GNU C++ compiler, g++, has a compiler command line option to switch between various different C++ ABIs.
As C++ evolved over the years, the Application Binary Interface (ABI) used by a compiler often needed changes to support new or evolving language features. Consequently, programmers were expected to recompile all their binaries with every new compiler release.
Is there some way I can automatically detect problems like this with GCC?
Only the linker can detect if you link incompatible code, not the compiler.
The alternative linker, gold
, can detect some problems with the --detect-odr-violations
option.
Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?
I just ensure I rebuild everything when I want to use the Debug Mode, I don't think I've ever wanted to keep a library around that was built with Debug Mode. It's meant for debugging, not for normal use.
I rarely use -D_GLIBCXX_DEBUG
anyway, I more often do something like:
#if 0
# include <debug/vector>
namespace my_class_stl = __gnu_debug;
#else
#include <vector>
namespace my_class_stl = std;
#endif
struct my_class
{
typedef my_class_stl::vector<int> container;
typedef container::iterator iterator;
// ...
};
Then I change the preprocessor condition when I want to use a Debug Mode vector for that specific class, without affecting every container in the program. Because the change involves writing to the file (and so updating its timestamp) anything that depends on that header will get rebuilt by make
, and there are two distinct types, std::vector<int>
and __gnu_debug::vector<int>
, which have different symbols and can't be confused by the linker.
Just defining _GLIBCXX_DEBUG
doesn't cause all dependencies to be rebuilt, and silently alters the definition of std::vector
globally, rather than changing specific containers to a different type with a different name, __gnu_debug::vector
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With