為什麼DLL在匯入項沒有成功解析時會載入失敗?

短答案

因為我們測試過其他方案,只有這種方式是最好的。

長答案

在16位的Windows系統上,如果一個模組沒有滿足其所有的匯入表,則它仍然可以被系統載入。只要你不呼叫一個丟失的匯入項,則一切都還是正常的。如果你嘗試呼叫一個丟失的匯入項,程式將會立即崩潰並顯示”不可恢復的錯誤”的對話方塊提示。

到了Win32時代,開發團隊覺得這是一個很糟糕的設計,因為有時候人們會將一個為Windows 3.1開發的應用程式拷貝到Windows 3.0上並執行,一開始,這個應用程式執行的還不錯,但是如果這個應用呼叫了一個只在Windows 3.1平臺上可用的函式時(例如,GetSaveFileName這個函式),應用程式會立即崩潰。

因此Win32開發團隊決定,如果有任何一個匯入項沒有被成功解析,則應用程式一開始載入的時候就會失敗。如果上面例子中的應用程式開發商希望能將他們的應用執行在Windows 3.0上,則可以通過顯式地使用GetProcAddress來表明這一點。因為如果必須顯式呼叫GetProcAddress,則可能需要檢查返回值。

當人們大聲疾呼時,有時會出現此問題:”天哪,我應該有一種方法可以將匯入項標記為’可選’-如果無法繫結,則載入應該不會失敗。在呼叫繫結之前,應用程式有責任驗證繫結是否成功。”,這些人可能是無意中在要求歷史的重演,因為這又會回到我們一開始碰到問題的地方。

總結

如果對一個函式呼叫在當前平臺上是否可用存在疑慮,可以嘗試先用GetProcAddress來獲取函式地址,如果函式不可用則進行相應的提示或者錯誤處理,儘量地讓你的應用優雅的退出。