posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          CSAPP - Linking - Strong and weak symbols

          Posted on 2007-08-02 23:45 ZelluX 閱讀(871) 評(píng)論(0)  編輯  收藏 所屬分類: C/C++ 、System
          《竊聽風(fēng)暴》的男主角烏爾里希·穆埃(Ulrich Mühe) 病逝了。。。
          好片子,好演員,可惜了。。。

          CSAPP 第七章Linking太枯燥了  啃了半天總算看到一點(diǎn)實(shí)際經(jīng)歷中遇到過的。

          在編譯階段,編譯器把全局變量標(biāo)記為strong或者weak,并導(dǎo)出到匯編程序中,由匯編程序把這些信息隱式地添加到relocatable object file的符號(hào)表(symbol table)中。
          函數(shù)和被初始化的全局變量被標(biāo)記為strong,未初始化的全局變量被標(biāo)記為weak。
          Unix連接器(linker)使用下面的規(guī)則來(lái)處理多個(gè)符號(hào)的情況:
          1. 不允許多個(gè)strong symbol的存在
          2. 如果有一個(gè)strong symbol和若干個(gè)weak symbol,使用strong symbol
          3. 只有若干個(gè)weak symbol,則使用其中任意一個(gè)

          幾個(gè)例子(未特殊說(shuō)明的情況,變量定義均在全局范圍):
          1. foo1.c和bar1.c中都有int main()方法,即存在了兩個(gè)strong symbol,連接器就會(huì)產(chǎn)生一條錯(cuò)誤信息。
          2.
          /* foo3.c */
          #include 
          <stdio.h>
          void f(void);

          int x = 15213;

          int main()
          {
              f();
              printf(
          "x = %d\n", x);
              
          return 0;
          }

          /* bar3.c */
          int x;

          void f()
          {
              x 
          = 15212;
          }
          main()方法調(diào)用f()后,x變?yōu)?5212并被輸出。
          注意這可能不是main()方法的作者原來(lái)的意圖。
          類似的情況也可能發(fā)生在兩個(gè)weak symbol同名的時(shí)候。

          3. 全局變量類型不同的情況:
          /* foo5.c */
          #include 
          <stdio.h>
          void f(void);

          int x = 15213;
          int y = 15212;

          int main()
          {
              f();
              printf(
          "x = 0x%x  y = 0x%x \n", x, y);
              
          return 0;
          }

          /* bar4.c */
          double x;

          void f()
          {
              x 
          = -0.0;
          }
          根據(jù)書上的內(nèi)容,
          linux> gcc -o foobar5 foo5.c bar5.c
          linux> ./foobar5
          結(jié)果應(yīng)該是
          x = 0x0  y = 0x80000000

          但是在自己機(jī)器上編譯時(shí)報(bào)錯(cuò)了,可能連接器版本較高,會(huì)自動(dòng)找出這種錯(cuò)誤
          /usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o
          是double和int大小不義導(dǎo)致的對(duì)齊問題


          這些問題都比較細(xì)小難以被查覺,通常在程序執(zhí)行了一段時(shí)間后才出現(xiàn)較嚴(yán)重的問題,因此很難被修復(fù),尤其當(dāng)許多程序員不清楚連接器的工作方式的時(shí)候。
          另外可以使用GCC的-warn-common標(biāo)記(flag),使得它在解析多個(gè)同名的全局變量時(shí)發(fā)出警告。
          試了下沒成功@@
          gcc --warn-common提示無(wú)法識(shí)別的命令行選項(xiàng),gcc -Wall則不會(huì)發(fā)出警告。
          主站蜘蛛池模板: 南雄市| 泽库县| 林周县| 图木舒克市| 岳阳市| 容城县| 汶川县| 盐边县| 扶绥县| 昌邑市| 肇庆市| 湖口县| 井陉县| 色达县| 新干县| 南通市| 山阴县| 合作市| 光山县| 白银市| 鲁甸县| 佳木斯市| 山阴县| 石城县| 澄江县| 娄烦县| 社旗县| 米脂县| 扎兰屯市| 大余县| 红原县| 绵阳市| 芷江| 城步| 花莲县| 弥渡县| 喜德县| 绵阳市| 乐清市| 临汾市| 平凉市|