title: Violating the one definition rule by simply linking dynamically
body: <p><strong>Question:</strong> Are dynamically linked C++ programs on ELF platforms always on the brink of producing undefined behavior by violating the one definition rule?</p>
  
  <p><strong>More specific:</strong> By simply writing a shared library exposing one function</p>
  
  <pre><code>#include &lt;string&gt;
  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();
  }
  </code></pre>
  
  <p>and compiling it with GCC 7.3.0 via</p>
  
  <pre><code>$ g++ -Wall -g -fPIC -shared \
        -fvisibility=hidden -fvisibility-inlines-hidden \
        -o liblibrary.so library.cpp
  </code></pre>
  
  <p>I create a binary which defines a weak symbol for the <code>operator+()</code> of a pointer to a character array and a string:</p>
  
  <pre><code>$ readelf -sW liblibrary.so | grep "_ZStpl"
      24: 0000000000000ee2   202 FUNC    WEAK   DEFAULT   12 _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_
      ...
  </code></pre>
  
  <p>But looking at the standard library binary I got</p>
  
  <pre><code>$ 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
  </code></pre>
  
  <p>That's the point where I say: <em>Oh my gosh,</em> the symbol inside my library ought to have a version attached to it too!</p>
  
  <p>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 <code>GLIBCXX_3.4.22</code>? 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.</p>