回應 tfing 的問題

tfing 在我這篇《新同事》詢問,為甚麼我遇到的一些情況,是不好的。寫一寫發現太多了,乾脆另開一篇。

在 VC6 裡,做 .lib 時,是不會檢查 dependency 的。也就是說,如果你呼叫了另外一個 .lib 的 function,只有 compiler 會檢查該 function 有否宣告過,linker 不會檢查該 symbol 是否存在。因此,如果 include path 有設,header 也有 #include,就不會顯示任何錯誤。必須要等到用該 .lib 的人,在做 .exe 或 .dll 時,才會產生 missing symbol 的錯誤。[1]

另外,.lib 相當於是把所有 function 都赤裸裸地開放出來,這樣就沒有所謂的「模組介面」,因此很容易就會亂呼叫 function,而沒有注意到,呼叫了不應有相依關係的 component 裡的函式[2]。又由於前述不會有 missing symbol 錯誤的關係,而無法察覺這樣的錯誤,因而導致最終程式的 dependency 關係會一團亂。

亂 call function,除了上面「呼叫了不應有相依關係的 component 裡的函式」的狀況之外,還包含了「喜歡自行在 .c/.cpp 檔前面,重複宣告函式,而不是用 #include 將對應的 header 引入」。 這會造成當所依存的 component 更新,prototype 改變時,會無法於 compile-time 察覺,若僅 prototype 改變,function name 不變的話,甚至連 link-time 也不會產生 error,假使 test-time 還是無法測到這個問題[3],那就等著在客戶那邊爆炸。

愛 copy & paste,則是指在沒有「乾淨」的 API 的情況下,大家都把「呼叫底層函式或改變資料結構的邏輯」抄來抄去,但這個「邏輯」隨著時間,一直在改變,於是就……。


  1. GCC/FreeBSD 沒有這樣子的問題,做 .a 的時候,就會檢查 symbol 存不存在。
  2. 舉例來說,libA 呼叫 libB,然後 libB 又呼叫 libA 這種 circular dependency 可能會造成一些問題,因此有時候會有「嚴格規定 component dependency」的 policy 存在。
  3. Test coverage 不夠,這在沒有計劃性地進行全面測試時,幾乎都會發生。

3 Comments

  1. tfing
    Posted May 16, 2007 at 10:26 pm | Permalink

    感謝站長的回答,學了不少東西

    不過有個問題
    "喜歡自行在 .c/.cpp 檔前面,重複宣告函式,而不是用 #include 將對應的 header 引入"
    這句的意思是使用extern function_name(...)這樣嗎?

    另外,我可以把這篇的連結po到我系上的BBS上嗎
    goodguy.csie.ncku.edu.tw -> G-SKB.TW

  2. Posted May 17, 2007 at 1:37 am | Permalink

    關於 missing symbol. MSVC 產生的 library (.lib) 是沒有被 fully linked (by default?). 也就是說產生一個 library 時並不用 (不能?) 滿足該 library 的 linker dependency. 這點與 GCC 不同. 但 MSVC 在產生 executable 與 dynamic library (shared library, in GCC's term) 時又與 GCC 一樣, 需要滿足 linker dependency. 我對 compiler 的了解的不夠多, 不知道這些 MSVC 與 GCC 的同與不同點的原因為何. 稍微做了一下 Internet search, 沒找到有用的資料, 看看你這篇能不能引出高手來做說明.

    第三段. .lib 沒有所謂的「模組介面」, 我沒看懂, 可以再做說明嗎? 至於 library dependency, 我想是一個合格的 MSVC developer 應該得需要去 manage 的.

    自行宣告函式而不 include 對應 header. 真是糟糕, 這不是跟 extern global 變數差不多? 你們該做 code review 了啊~

    我曾經被一位前輩/上司教誨 - copy & paste 就是 code reuse. Oh, my god!!!

  3. Posted May 21, 2007 at 1:21 pm | Permalink

    Oh....

    我多麼慶幸自己的開發環境是GCC, 「可以幸災樂禍」的感覺真好 XD

    不過GCC環境有是有些很精彩的noob tips, 有機會再聊聊.