VS2015編譯(工具集v140,對應MSVC 14.0,運行庫`MSVCR140.dll`),卻報缺`MSVCR120.dll`(VS2013運行庫),原因是**項目依賴的第三方靜態庫/動態庫是用VS2013編譯的**,將其依賴傳遞給了最終EXE。本文記錄排查全過程與解決方案。
現象與誤區
- 項目屬性 → C/C++ → 代碼生成 → 運行庫 已設置 `MT` (多線程靜態) / `MD` (多線程動態)。
- 但依然報缺 `MSVCR120.dll` — **說明有二進制模塊強依賴VS2013 CRT**。
- 常見誤區:以為改項目設置能解決,實則**第三方庫已鏈接死對應CRT版本**。
排查步驟
- Dependency Walker / `dumpbin /dependents your.exe` 查看EXE直接依賴的DLL,確認是否含`MSVCR120.dll`。
- 檢查所有鏈接的.lib/.dll:第三方SDK、開源庫預編譯二進制、歷史項目輸出庫。
- 確認第三方庫編譯工具集**:查閱文檔、詢問提供方、或用`dumpbin /headers libname.lib`查看`machine`與`subsystem`版本。
解決方案(按推薦順序)
方案一:重新編譯第三方庫源碼(徹底)
- 獲取第三方庫源碼。
- 用**當前項目相同工具集(VS2015 v140)**編譯生成新`.lib/.dll`。
- 替換項目依賴,重新鏈接。
- 優點:消除版本衝突,統一CRT,避免雙CRT運行風險(堆/鎖/文件句柄不互通)。
方案二:安裝VC++ 2013 Redistributable(臨時/無源碼時)
- 目標機安裝 `vcredist_x86/x64.exe` (VS2013)。
- 缺點:部署麻煩、雙CRT共存風險、不符合「綠色軟件」預期。
方案三:延遲加載/動態加載隔離(架構調整)
- 將使用第三方庫的代碼隔離在單獨DLL中,該DLL鏈接VS2013 CRT。
- 主程序(VS2015)通過`LoadLibrary`/`GetProcAddress`動態調用隔離DLL。
- 缺點:接口設計複雜、跨DLL邊界傳遞STL/CRT對象極危險(需純C接口/POD類型)。
驗證與預防
- 發布前在**乾淨虛擬機**(無任何VC++ Redist)測試運行。
- CI/CD流程集成依賴檢查腳本,禁止引入非統一工具集編譯的二進制依賴。
- 新項目從源碼編譯所有依賴(vcpkg/Conan包管理器極大簡化此流程)。
鐵律:同一進程內所有模塊必須使用同版本CRT。第三方庫無源碼無法重編時,隔離加載或放棄該庫。