title: Address sanitizer error when using boost serialization
body: <p>I've recently tried to use boost serialization to serialize a class which contains a <code>std::vector&lt;std::unique_ptr&lt;Base&gt;&gt;&gt;</code> as a member. According to the boost documentation (<a href="https://www.boost.org/doc/libs/1_71_0/libs/serialization/doc/serialization.html#derivedpointers" rel="nofollow noreferrer">https://www.boost.org/doc/libs/1_71_0/libs/serialization/doc/serialization.html#derivedpointers</a>), we must register the derived classes using method <code>register_type</code> of the archive for the serialization to work properly. Everything indeed builds and run fine but address sanitizer build (which runs in our CI) is failing with the following error:</p>
  
  <pre><code>ASAN:DEADLYSIGNAL
  =================================================================
  ==3==ERROR: AddressSanitizer: SEGV on unknown address 0x000000100000 (pc 0x559bc5f18288 bp 0x7ffe74fd8d30 sp 0x7ffe74fd8d10 T0)
  ==3==The signal is caused by a READ memory access.
  ==3==Hint: address points to the zero page.
      #0 0x559bc5f18287 in boost::serialization::void_cast_detail::void_caster_primitive&lt;Derived, Base&gt;::void_caster_primitive() /usr/include/boost/serialization/void_cast.hpp:188
      #1 0x559bc5f1714a in boost::serialization::singleton&lt;boost::serialization::void_cast_detail::void_caster_primitive&lt;Derived, Base&gt; &gt;::get_instance()::singleton_wrapper::singleton_wrapper() /usr/include/boost/serialization/singleton.hpp:117
      #2 0x559bc5f173be in boost::serialization::singleton&lt;boost::serialization::void_cast_detail::void_caster_primitive&lt;Derived, Base&gt; &gt;::get_instance() /usr/include/boost/serialization/singleton.hpp:118
      #3 0x559bc5ef3294 in __static_initialization_and_destruction_0 /usr/include/boost/serialization/singleton.hpp:155
      ...
  </code></pre>
  
  <p>Upon inspecting what is in <code>void_cast.hpp</code>, I've discovered the problematic code in the constructor of <code>void_caster_primitive</code>:</p>
  
  <pre><code>/* note about displacement:
   * displace 0: at least one compiler treated 0 by not shifting it at all
   * displace by small value (8): caused ICE on certain mingw gcc versions */
  reinterpret_cast&lt;std::ptrdiff_t&gt;(
      static_cast&lt;Derived *&gt;(
          reinterpret_cast&lt;Base *&gt;(1 &lt;&lt; 20)
      )
  ) - (1 &lt;&lt; 20)
  </code></pre>
  
  <p>Judging by the code and the comment, this expression is calculating the displacement of <code>Base</code> class within <code>Derived</code>. However, it still looks like magic, especially with casting a (seemingly) random number to a <code>Base</code> pointer. It would be great if someone could shed some light on why this actually calculates the displacement.</p>
  
  <p>EDIT:
  Here is a simple example that uses the displacement calculation method shown above: <a href="https://godbolt.org/z/Bmp7zH" rel="nofollow noreferrer">https://godbolt.org/z/Bmp7zH</a> It compiles and runs if sanitizer is turned off, but after it is turned on, the program terminates abnormally.</p>
  
  <p>This is also an attempt to reproduce the original issue with SEGV on compiler explorer: <a href="https://godbolt.org/z/w8ZNx8" rel="nofollow noreferrer">https://godbolt.org/z/w8ZNx8</a> However, linking boost serialization doesn't seem to work, and also if I turn on the sanitizer options, the build sometimes times out.</p>