本來在DEBUG下運行的非常好,可是換成release後就出現了各種的內存讀寫錯誤,話說在DEBUG下,沒有初始化的變量都被初始化爲零了,而在RELEASE下則是隨機數值,然後就各種查找錯誤,最後看到把動態鏈接庫改成靜態鏈接庫,我就試了一下,終於行了,哎,不得不說WINDOWS啊你不地道。。。
網上查了一下靜態鏈接庫和動態鏈接庫的區別,我簡單總結一下:
1、如果是靜態鏈接庫模式,程序是把目標代碼從庫文件拷貝到執行文件,這樣在DLL不在的情況下,程序依舊可以運行,動態則是運行過程中加載,前提是你要有DLL可以提供加載
2、明顯靜態模式下最終程序要大,而動態要小
遺憾地說:除了ender說的是正確的外,其他觀點都有偏頗之處甚至是錯誤的。我的感覺是,大家受MFC的影響太深了,而沒有看到事情的本質。
首先糾正所謂“靜態連接就是把需要的庫函數放進你的exe之中”的說法。在真實世界中,有三個概念:Use static libary, static linked DLL, dynamic linked DLL.
多數人混淆了static libary 和 static linked DLL的概念,當然他們有似是而非的“相似之處”,比如都用到.lib,下面具體說明。
使用靜態庫(Use static libary)是把.lib和其他.obj一起build在目標文件中,目標文件可以是.exe,也可以是.dll或.oxc等。一般情況下,可以根本就沒有“對應的”.dll 文件,如C Run Time(CRT)庫。一個例子就是,寫一個main(){},build出來並不是只有幾個字節,當然有人會說那還有exe文件頭呢?是,即使加上文件頭的尺寸,build出的執行文件仍然“莫名的大”。實際上那多出來的部分就是CRT靜態庫。姑且可以把靜態庫.lib理解成外部程序的obj文件比較合理,它包含了函數的實現。
下面再談static linked DLL 和 dynamic linked DLL又如何?
靜態鏈接 (static linked DLL)從操作上在VC的Project|Settings...|Link (tab)|General (category)|Object/library modules 中設置和添加。比如要使用SDK中的PropertySheet() API, 就要在這裏添加
comctl32.lib,然後再調用的源程序中#include <prsht.h> , 使用的地方直接調用PropertySheet()。當程序.exe啓動時,系統會把對應comctl32.dll加載進來。作爲DLL的靜態引入庫的.lib不包含函數的實現,只包含用於系統加載的信息,如對應的DLL名稱,函數歧視地只在對應的DLL中的便宜等等。相比動態鏈接而言,靜態鏈接是很簡單的。
動態鏈接是使用LoadLibrary()/GetProcessAddress()和FreeLibrary(),詳見下面的例子。
{
typedef BOOL (WINAPI *LPFNSHELLEXECUTEEX)(LPSHELLEXECUTEINFO);
hShell32Dll = LoadLibrary(TEXT( "SHELL32.DLL "));
if (!hShell32Dll) { goto End; }
lpfnShellExecuteEx = (LPFNSHELLEXECUTEEX)GetProcAddress(hShell32Dll,
API_NAME(ShellExecuteEx));
if (!lpfnShellExecuteEx) { goto End; }
...
fOk = (*lpfnShellExecuteEx)(pShellExecuteInfo);
...
End:
if (hShell32Dll) {
FreeLibrary(hShell32Dll);
}
lpfnShellExecuteEx = NULL;
...
}
有人會想,動態鏈接這樣麻煩,爲什麼還要用呢?這裏有一個技術問題,對這個問題的解決直接導致了動態加載的需求。問題是有些DLL只在某個Windows版本中存在,或某個API只在某些Windows版本中被加入指定的DLL。當你使用靜態鏈接的.exe試圖在不支持的Windows版本上運行時,系統會彈出系統對話框提示某某.dll無法加載或無法定位某某API的消息,然後就中止.exe的運行。像這樣因爲個別功能的實現依賴於某個DLL,當這個DLL不可用時導致整個.exe無法運行是不明智的。避免這樣的結局只有用動態鏈接。