title: Struct of shared pointers and callback registration. Raw pointer value changed when callback is called for reasons beyond me
body: <p>I have implemented an interface for registering callbacks but have encountered an issue that is beyond me.</p>
  
  <p>In particular, if a function is registered as a callback with an copy of a structure of shared pointers specified as the argument, the shared pointers' raw pointer value changes when the callback is called, causing segmentation fault to occur if the pointers are dereference (since it is no longer pointing to the original object). However, when I register the callback with a reference to the structure of shared pointers. It works fine.</p>
  
  <p>To get what I mean, consider the following code blocks.</p>
  
  <p><code>test.h</code> and <code>test.c</code> contain the interface and implementation for callback registrations respectively, while <code>test_cb.cpp</code> is the main client code using this interface.</p>
  
  <p><strong>test.h</strong></p>
  
  <pre><code>#ifndef __TEST_H__
  #define __TEST_H__
  
  #ifdef __cplusplus
  extern "C"
  {
  #endif
  
  typedef void (*TestFnCb)(void *pArgs);
  
  void RegisterCallback(TestFnCb fn, void *pArgs);
  
  void PeriodicActions();
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  </code></pre>
  
  <p><strong>test.c</strong></p>
  
  <pre><code>typedef struct TestFnData
  {
    TestFnCb pFunc;
    void *pArgs;
  } TestFnData;
  
  TestFnData fndata; 
  
  void RegisterCallback(TestFnCb fn, void *pArgs)
  {
    fndata.pFunc = fn;
    fndata.pArgs = pArgs;
  }
  
  void PeriodicActions()
  {
    while(1)
    {
      if(fndata.pFunc)
      {
        fndata.pFunc(fndata.pArgs);
      }
      usleep(1000000);
    }
  }
  </code></pre>
  
  <p><strong>test_cb.cpp</strong>:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;thread&gt;
  #include &lt;memory&gt;
  #include "test.h"
  
  class B
  {
  public:
    virtual void print()
    {
      std::cout &lt;&lt; "B::print()\n";
    }
  };
  
  class D: public B
  {
  public:
    void print() override
    {
      std::cout &lt;&lt; "D::print()\n";
    }
  };
  
  struct TestStruct
  {
    std::shared_ptr&lt;B&gt; m1;
    std::shared_ptr&lt;B&gt; m2;
  };
  
  TestStruct myStruct;
  
  void ThreadFuncProc()
  {
    while(1)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
  }
  
  void MyCallback(void *pArgs)
  {
    TestStruct *pStruct = static_cast&lt;TestStruct*&gt;(pArgs);
    std::cout &lt;&lt; "MyCallback: pStruct " &lt;&lt; pStruct &lt;&lt; "\n";
    std::cout &lt;&lt; "MyCallback: myStruct.m1.get(): " &lt;&lt; pStruct-&gt;m1.get() &lt;&lt; "\n";
    std::cout &lt;&lt; "MyCallback: myStruct.m2.get(): " &lt;&lt; pStruct-&gt;m2.get() &lt;&lt; "\n";
    pStruct-&gt;m1-&gt;print(); // Segfault here because m1.get() isn't pointing to the correct raw pointer.
    pStruct-&gt;m2-&gt;print();
  }
  
  void TestInit(TestStruct testSt) // This is not.
  // void TestInit(TestStruct &amp;testSt) // This is fine.
  {
    std::cout &lt;&lt; "TestInit: &amp;testSt: " &lt;&lt; &amp;testSt &lt;&lt; "\n";
    std::cout &lt;&lt; "TestInit: testSt.m1.get(): " &lt;&lt; testSt.m1.get() &lt;&lt; "\n";
    std::cout &lt;&lt; "TestInit: testSt.m2.get(): " &lt;&lt; testSt.m2.get() &lt;&lt; "\n";
    RegisterCallback(MyCallback, &amp;testSt);
  }
  
  int main(int argc, char **argv)
  {
    myStruct.m1 = std::make_shared&lt;D&gt;();
    myStruct.m2 = std::make_shared&lt;D&gt;();
  
    std::cout &lt;&lt; "myStruct.m1.get(): " &lt;&lt; myStruct.m1.get() &lt;&lt; '\n';
    std::cout &lt;&lt; "myStruct.m2.get(): " &lt;&lt; myStruct.m2.get() &lt;&lt; '\n';
    TestInit(myStruct);
    std::thread t1(ThreadFuncProc);
    std::thread t2(PeriodicActions);
    t1.join();
    t2.join();
    return 0;
  }
  </code></pre>
  
  <p>As you can see, I've created two shared pointer objects, each encapsulating a pointer to an instance of class <code>D</code>. <code>TestInit()</code> is then called with a struct containing the two shared pointer objects. It simply registers <code>MyCallback()</code> as the callback and passing in the struct. Here is where it gets weird. If <code>TestInit()</code> is defined to accept a <code>TestStruct &amp;</code> instead of <code>TestStruct</code>, everything is fine. </p>
  
  <p><strong>Output</strong>
  </p>
  
  <pre><code>$ gcc -o test.o -c test.c
  $ g++ -o test_cb.o -c test_cb.cpp -std=c++11
  $ g++ -o main test_cb.o test.c -lpthread
  $ ./main
  myStruct.m1.get(): 0x6bdc30
  myStruct.m2.get(): 0x6bdc50
  TestInit: &amp;testSt: 0x7fff9578e470
  TestInit: testSt.m1.get(): 0x6bdc30
  TestInit: testSt.m2.get(): 0x6bdc50
  MyCallback: pStruct 0x7fff9578e470
  MyCallback: myStruct.m1.get(): 0x7f303f730700
  MyCallback: myStruct.m2.get(): 0x6bdc50
  Segmentation fault (core dumped)
  </code></pre>
  
  <p>What I don't get is why does the copy's <code>m1.get()</code> in <code>TestInit()</code> have the same output as that in <code>main()</code> but not when they are called in <code>MyCallback()</code>. <code>pStruct</code> is clearly pointing to the copy of the struct in <code>TestInit()</code>. What has caused the encapsulated raw pointer of <code>m1</code> to change? And, why <code>m2</code> doesn't have this problem?</p>
  
  <p>I'm utterly confused why this is happening. I have run out of hypothesis to test.</p>
  
  <p>Any insight will be greatly appreciated!</p>