解決某些 C++ 程式在 VC2005 debug 模式下找不到 MSVCR80.DLL 的問題

恩…自己寫完後,都覺得真是超長的一個標題。首先呢,這個問題的發生,主要是因為 Heresy 這邊工作上目前都是用 Visual Studio 2005 來寫 C 的程式;而為了簡化開發呢,在不少非核心的部分(例如讀取影像檔案),有使用一些現有的 Open Source 函式庫。而這次碰到的問題,就是在使用 libgeotiff 時發生的了…

主要狀況,就如同標題所述,只要執行某些 debug 版的程式,就會出現找不到 MSVCR80.DLL 的問題(如下圖對話框);而相對的,release 版則沒有任何問題。

image

MSVCR80.dll 基本上是微軟的 C Runtime Library 的一個檔案,在執行 Visual C 2005 (8.0) 所編譯的程式時,大多需要這個檔案;對於一般使用者來說,只要有安裝對應的「可轉發套件」(例如:Microsoft Visual C 2005 SP1 可轉散發套件 x86x64),大多就會把檔案複製到系統裡了∼而實際上,目前有不少程式都會先自動裝上這東西。

而理論上,在有安裝 Visual Stuio 的電腦上,不應該會出現這樣的問題?本來一直以為是 Windows 或 Visual Studio 的設定爛掉了,後來找了老半天,才發現其他程式似乎沒有類似的問題;後來再進一步釐清,似乎和設定無關,而是其他方面的問題。到目前為止,Heresy 是認定這應該是「部分有使用到 release 版 libgeotiff 的程式」才有的問題;而類似的問題(不見得是 libgeotiff),其實在網路上也是找的到討論的。

發生的原因呢?似乎是因為 debug 版的程式,用了 release 版的動態函式庫,導至在某些其況下,會沒有辦法正確地讀取 release 版的 MSVCR80 所造成的(話說,libtiff 就不會有這問題?)。

最根本的解決方法,應該就是把所有函式庫,都各自建置 release、debug 兩種版本了∼但是其實這樣滿麻煩的,不但在一般情況下,不太可能會進去追函式庫裡的程式;而且如果是像 Heresy 這邊還有 win32 和 x64 的話…就變成要維護四種版本了… orz

後來有找到兩種可能的解法,其實意義是一樣的;就是要把相依性(dependency)的資訊,強制加到程式的執行檔裡。而所需的相依性資訊的來源,其實就是 VC 2005 在編譯後會產生的 manifest 檔(中文版把這個叫做「資訊清單檔」)了∼

解法一:在程式的原始碼內加入相依性資訊。

在程式的 .CPP 檔裡,加上

#pragma comment(linker, ""/manifestdependency:type=’Win32′ name=’Microsoft.VC80.CRT’ version=’8.0.50727.4053′ processorArchitecture=’X86′ publicKeyToken=’1fc8b3b9a1e18e3b’ language=’*’"")

後,再重新編譯,應該就可以在執行時強制去讀取正確的 dll 檔。

不過,內部的資訊,可能需要根據編譯函式庫時所產生的 manifest 檔(例如 Heresy 這邊是 geotiff.dll.manifest)做對應的修改;像在 x64 時,processorArchitecture 就要從 X86 改成 amd64。

所以這樣的方法,第一個麻煩是要修改原始碼;而且像同時有 win32 和 x64 的設定的話,就還必須要用 ifdef 的方法來處理,算是滿麻煩的…

解法二:在專案設定裡,設定要額外加上 manifest 檔。

由於解法一滿麻煩的,所以 Heresy 後來是透過專案的設定來解決。這個方法的設定方法如下:

  1. 在專案上按右鍵,選「Properties(屬性)」
  2. 然後找到「Configuration Properties(組態屬性)」、「Manifest Tool(資訊清單工具)」裡的「Input and Output(輸入和輸出)」
  3. 在「Additional Manifest Files(其他資訊清單檔)」裡,把函式庫的 manifest 檔加進去就可以了∼

image

而針對 win32 和 x64 這樣不同的平台,也只要設定加上不同的 Manifest 檔就好了∼

現階段知道的解法只有這樣啦∼可以的話,還是希望可以在編譯函式庫的時候,直接解決掉這問題,不用像現在這樣還要額外處理…不過也不知道能不能解就是了… ~_~

順帶一提,透過 mt 把 Manifest 的資訊加到函式庫的 DLL 檔裡似乎沒有用…


參考資料:

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。