隨筆-11  評論-10  文章-8  trackbacks-0
          這個題目一看就很欠扁,既然用C++又不想依賴stdlibc++標準庫這不是有病嗎?其意義究竟
          何在?這實際上就是我最近被賦予的光榮使命,神奇的是原來真的可以做到!!!與標準庫
          斗于編譯器斗,其樂無窮~~~收獲也不是沒有,對C++,對編譯器的認識又更近了一步,雖然
          本來就沒有什么認識。

          故事是這樣開始的,我們為公司的某產品開發了一個模塊,其實就是兩動態庫。本來這東西
          也不是我們開發的,我們只是負責移植到公司的12個平臺上。本來一切都很順利,不幸的事
          是在test快要結束的時候發生的,某平臺是build機器上與test機器上stdlibc++.so版本不
          一致,我們的so竟然不能load,這不是再正常不過的事情么,裝一個需要的版本就一了百了
          了,但是。。但是可惡的印度人懶得裝不說,還指責是我們的問題,說引入了新的依賴,不
          行不行就是不行,我的奇妙旅行就此開始了。(這個問題也可以通過靜態鏈接stdlibc++解
          決,貌似他們沒搞定,我也沒有深入研究)

          總的來說C++對stdlibc++.so的依賴主要由以下幾個部分產生:
          1. 對C++標準庫的依賴
             簡單的看就是 include C++的頭文件(不以.h結尾)
             如果你大量使用的STL...請回吧,不送了。還好我們只使用到了vector和dqueue,簡
             單實現了一個,湊合著用了
          2. new 和 delete 操作符
             這兩個操作符實際上完成了兩部分工作,首先是分配內存,其次是調用相應的構造/析構
             方法。而對于gcc來說,分配內存的工作是在stdlibc++.so中完成的,所以會造成依賴,
             幸運的是重載這兩個操作符就是重載分配內存的部分,所以我們只需要用malloc/free簡
             單的重載這兩個操作符就ok了
          3. 純虛函數
             使用繼承和虛函數都是沒問題的(竟然沒有依賴rtti,需要繼續研究),但純虛函數是
             不行的,這個估計跟實現有關。最簡單的方法就是將所用的純虛函數改為虛函數再添加
             默認實現。
          4. exception
             這是最麻煩的部分,如果exception用的不多,直接將exception作為返回值返回了結
             (原來有返回值的放到輸出參數里),每次調用check一下,根據原來代碼中的邏輯要么
             返回exception(沒有catch住該exception),要么做catch中的事。理論上是沒問題的
             就是麻煩點,代碼ugly點,可能再用點goto也沒啥大問題。
             這里要介紹的是另一種方法,通過使用setjmp和longjmp實現exception機制,再利用宏
             替換原來代碼中的try throw catch,詳細的就不寫了,我也是從網上看到的參見:
             Exception Handling in C without C++
             cexcept:sourceforge上的開源項目
             看了就能明白,但要實現完整的exception機制還是有難度的,包括try catch的嵌
             套,exception的繼承,多catch等。我們現在也沒能實現多catch,宏的能力還是有限啊。
          5. rtti
             這是C++特用的東西,嚴重依賴于stdlibc++.so,凡是動態的類型判斷都是要禁止
             的,catch為了判斷exception的類型就會使用到rtti,dynmaic_cast也會有同樣的問
             題,typeid之類的東西更是永不得的。
          6. 編譯參數
             當你完全完成了上面的工作,基本上就大功告成了,不過現代的編譯器那是相當的聰明,在
             背后為我們默默無聞的做了很多事情,比如對于c++的代碼會默認幫你生成處理
             exception的代碼,所以需要用 -fno-exceptions 來防止這樣的事情發生,然而這還不
             夠,-fno-exceptions 和 -fno-rtti 必須是要同時使用的,只使用 -fno-exceptions只
             能得到個半吊子的結果:依然會有rtti的代碼生成(不知道gcc那幫人是怎么想的)。
             你以為終于可以結束了嗎?
          if (your_gcc_version < 3.4.6) {
              goHome();
              happyEnding();
          else {
              聽我慢慢道來();
          }
             在gcc 3.4.6 以上版本會為local static生成保證線程安全的代碼,不幸的是這些代碼
             是依賴于stdlibc++.so的,所以我們要禁止他們!!!請使用
             -fno-threadsafe-statics,并確保這些static代碼是線程安全的

          終于寫完了,估計沒有人會再有這樣奇怪的需求了,寫在這里留作紀念。
             
          另外提一下模板是可以使用的,因為只是在編譯時生成代碼,不關標準庫的事。

          posted on 2008-07-31 00:05 JBahamut 閱讀(1067) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2008年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(1)

          隨筆檔案

          文章檔案

          收藏夾

          link

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 汕尾市| 古交市| 弥勒县| 南平市| 新邵县| 木里| 阿巴嘎旗| 札达县| 淮阳县| 广水市| 吴旗县| 同心县| 尼玛县| 平果县| 大洼县| 屏东市| 丘北县| 湘潭县| 淮北市| 崇明县| 西城区| 汉源县| 永泰县| 鄯善县| 天峨县| 桐乡市| 广元市| 乌拉特前旗| 大丰市| 清涧县| 青冈县| 雷州市| 平谷区| 开鲁县| 长汀县| 北海市| 南丹县| 梧州市| 临沭县| 肇庆市| 平武县|