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 不夠,這在沒有計劃性地進行全面測試時,幾乎都會發生。