so true

          心懷未來,開創未來!
          隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
          數據加載中……

          some notes on linking with shared library

          ==> Object.h <==
          #include <stdio.h>

          class Object {
          public:
              Object();
          #ifdef TEST
              void NoneVirtualFunc() {
                  printf("%s, size of class:%lu\n", __PRETTY_FUNCTION__, sizeof(Object));
              }
          #endif

          #ifdef TEST
              virtual void Func2();
              virtual void Func1();
          #else
              virtual void Func1();
              virtual void Func2();
          #endif
              virtual void Access();

          #ifdef TEST
              void SetOther(int other) {
                  m_other = other;
              }
              virtual void Other() {
                  printf("%s\n", __PRETTY_FUNCTION__);
              }
          #endif

          private:
              int m_i1;
          #ifdef TEST
              int m_other;
          #endif
              int m_i2;
          };

          ==> Object.cpp <==
          #include "Object.h"

          Object::Object(): m_i1(1), m_i2(2) {
              printf("%s, constructor init, i1:%d, i2:%d\n", __PRETTY_FUNCTION__, m_i1, m_i2);
          }

          void Object::Func1() {
              printf("%s\n", __PRETTY_FUNCTION__);
          }

          void Object::Func2() {
              printf("%s\n", __PRETTY_FUNCTION__);
          }

          void Object::Access() {
              printf("%s, size of class:%lu, i1:%d, i2:%d\n", __PRETTY_FUNCTION__, sizeof(Object), m_i1, m_i2);
          }

          ==> test.cpp <==
          #include "Object.h"

          //for more details about vtable, see: http://blog.csdn.net/haoel/article/details/1948051

          int main(int argc, char* argv[]) {
              Object* obj = new Object();

              obj->Func1();
              obj->Func2();
          #ifdef TEST
              obj->SetOther(1000);
          #endif
              obj->Access();

          #ifdef TEST
              obj->NoneVirtualFunc();
              obj->Other(); //segmentation fault
          #endif

              return 0;
          }


          ==> Makefile <==
          all:
              @g++ -g -fPIC -o Object.o -fno-rtti -c Object.cpp
              @g++ -shared -o libObject.so Object.o
              @g++ -g -Wall test.cpp -o test -L. -lObject -Wl,-rpath=.
              @./test
              @rm -f test *.o *.so core*


          test:
              @g++ -g -fPIC -o Object.o -fno-rtti -c Object.cpp
              @g++ -shared -o libObject.so Object.o
              @g++ -g -Wall test.cpp -o test -L. -lObject -Wl,-rpath=. -DTEST
              @./test
              @rm -f test *.o *.so core*

          ==> RESULT <==
          $ make
          Object::Object(), constructor init, i1:1, i2:2
          virtual void Object::Func1()
          virtual void Object::Func2()
          virtual void Object::Access(), size of class:16, i1:1, i2:2

          $ make test
          Object::Object(), constructor init, i1:1, i2:2
          virtual void Object::Func2()
          virtual void Object::Func1()
          virtual void Object::Access(), size of class:16, i1:1, i2:1000
          void Object::NoneVirtualFunc(), size of class:24
          make: *** [test] Segmentation fault (core dumped)
          make: *** Deleting file `test'

          ==> KNOWLEDGE <==
          一個類一旦已經編譯成so了,那么虛函數以及成員變量就都確定了,也就是影響一個類的內存映像的東西都是確定的了。
          所以,修改頭文件時需要遵循以下原則:
          1??梢噪S意添加非虛函數;
          2。不要修改虛函數的相對位置,更不要添加新的虛函數;
          3。最好不要添加新的成員變量,如果添加也要在所有成員變量的后面添加,不過如果你不清楚so里的用法的話,很有可能出問題;

          其實,說到本質上,就是要心里很清楚,修改前和修改后,該類的內存映像到底是怎樣的,固化在so里的代碼是不會再變化了;
          有興趣的,可以debug看下虛函數表里指針的情況;如果不用-fno-rtti參數,那么vtable里會多出兩項用于typeinfo相關的內容;
          增加了新的虛函數后,通過nm -C test | grep Object可以看到,生成的可執行程序里是不會有Other這個虛函數的:
          00000000004008f8 W Object::NoneVirtualFunc()
          0000000000400920 W Object::SetOther(int)
                           U Object::Object()
          0000000000400a60 r Object::NoneVirtualFunc()::__PRETTY_FUNCTION__

          而且新加的函數都是W類型,下面通過另一個例子來驗證W類型:
          ==> Object.h <==
          #include <stdio.h>

          class Object {
          public:
              void func() {
                  printf("It's the implementation of %s in header file\n", __PRETTY_FUNCTION__);
              }
          };

          ==> test.cpp <==
          #include <stdio.h>
          #include "Object.h"

          int main(int argc, char* argv[]) {
              Object obj;
              obj.func();
              return 0;
          }

          ==> RESULT <==
          $ g++ -o test test.cpp
          $ ./test
          It's the implementation of void Object::func() in header file

          ==> Object.cpp <==
          #include <stdio.h>
          class Object {
          public:
              void func();
          };

          void Object::func() {
              printf("%s\n", __PRETTY_FUNCTION__);
          }

          ==> RESULT <==
          $ g++ -c -o Object.o Object.cpp
          $ g++ -o test test.cpp Object.o
          $ ./test
          void Object::func()

          posted on 2015-03-12 20:50 so true 閱讀(279) 評論(0)  編輯  收藏 所屬分類: C&C++

          主站蜘蛛池模板: 安丘市| 德清县| 南阳市| 武川县| 山西省| 银川市| 凤城市| 定安县| 龙泉市| 柳江县| 喀什市| 西乌珠穆沁旗| 汉中市| 武强县| 哈尔滨市| 临湘市| 毕节市| 英德市| 珠海市| 东阿县| 澄迈县| 德州市| 东乌珠穆沁旗| 利辛县| 郎溪县| 永靖县| 九寨沟县| 丽水市| 怀来县| 电白县| 府谷县| 宁陵县| 布尔津县| 顺昌县| 阿瓦提县| 微山县| 丹江口市| 泽库县| 霍城县| 安平县| 岳普湖县|