问题
Question: Are dynamically linked C++ programs on ELF platforms always on the brink of producing undefined behavior by violating the one definition rule?
More specific: By simply writing a shared library exposing one function
#include <string>
int __attribute__((visibility("default"))) combined_length(const char *s,
const char *t)
{
const std::string t1(t);
const std::string u(s + t1);
return u.length();
}
and compiling it with GCC 7.3.0 via
$ g++ -Wall -g -fPIC -shared \
-fvisibility=hidden -fvisibility-inlines-hidden \
-o liblibrary.so library.cpp
I create a binary which defines a weak symbol for the operator+()
of a pointer to a character array and a string:
$ readelf -sW liblibrary.so | grep "_ZStpl"
24: 0000000000000ee2 202 FUNC WEAK DEFAULT 12 _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_
...
But looking at the standard library binary I got
$ readelf -sW /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep "_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_"
2829: 000000000012b1c0 169 FUNC WEAK DEFAULT 13 _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_@@GLIBCXX_3.4.21
That's the point where I say: Oh my gosh, the symbol inside my library ought to have a version attached to it too!
In the current state I'm fine because I can assume that the standard library binary is built with the same headers as my library. But what happens if the implementers of libstdc++-v3 decide to define a new version of this function and tag it with GLIBCXX_3.4.22
? Since the symbol is weak, the runtime linker is free to decide whether it takes the unversioned symbol of my library or the versioned symbol of the libstdc++-v3. If I ship my library to such a system I provoke undefined behavior there. Something symbol versions should have solved for me.
来源:https://stackoverflow.com/questions/52223788/violating-the-one-definition-rule-by-simply-linking-dynamically