int main(int argc, char* argv)
return 0;
}//dll中
void testfile(file *fp)
這樣出錯, 提示00000010位址不能為寫!
先解釋幾個基本概念:
1,重複定義
出現變數或者函式重複定義,vc6一般報這樣乙個錯誤:fatal error lnk1169: one or more multiply defined symbols found
這個錯誤表明某個符號在工程中被定義了兩份。這種情況一般發生在,某個變數在多個原始檔(注:區別於標頭檔案)出現定義。
2,工程間原始檔分享
這種分享有兩種方式,一種是通過.h檔案單獨分享,一般情況下,這種分享是安全的。
另一種是通過.h + .lib,或者 .h + .c,.cpp共享,這時候就會發生所謂的「隱式重複定義」。
觀察問題中的結構,可以發現問題的起因就是file *指標的共享,那麼在fopen,fwrite之類的函式中,到底對file *做了些什麼呢?
除錯這個源**,可以在
_file.c
檔案中跟蹤到如下**:
void __cdecl _lock_file (
void *pf
)這是在fread中呼叫到的乙個函式,注意函式中的這句:
if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_iob_entries-1])) )
這裡和 pf 比較的變數 _iob 是唯一沒有跟隨file * (pf)一起傳遞的變數,那麼問題是否就出在這裡呢?
在這個檔案中,找到了 _iob的定義:
file _iob[_iob_entries] = ,
/* stdout (_iob[1]) */
,/* stderr (_iob[3]) */
,這樣一來,問題就清楚了。
_file.c是乙個公共原始檔,工程exe和dll分別引用了這個檔案。
於是在exe中和dll中,這個變數_iob就存在了兩份(隱式重複定義),而這個變數是影響相關函式執行結果的乙個變數。(這個問題也會出現在使用lib作為公共原始檔的場合)
在exe中,呼叫fopen,fread等函式的時候,內部呼叫的是鏈結進exe檔案的_iob,而dll的匯出介面呼叫的,是鏈結進dll內部的同名變數。
問題發生了,exe中的改變並不會影響dll中同名變數的數值,那麼當在exe中想當然的認為正確的數值,到了dll中就面目全非了,結果必然是出錯。
解決這個問題的方法有四個:
1,修改dll,把所有相關的函式,包括fopen,fread,fwite等全部匯出。
這樣做可以確保所有呼叫引用的_iob都指向dll內部的版本,但是由於涉及的函式比較多,操作複雜,並且影響dll外部介面的清晰。
2,修改程式邏輯,把傳遞file * 改為傳遞自定義的檔案緩衝區指標。
這樣可以完全避免問題,同時程式的介面也將更簡單。
3,修改_file.c及相關庫的實現。
這麼作的好處是一勞永逸,並且也為其他庫的使用者避免了麻煩(當然,使用者還是需要更新庫檔案並且重新編譯鏈結),只是這個恐怕需要庫**商的支援,並且是否可行還有待商榷。
file *不允許在exe和dll之間作為介面引數傳遞。
查閱了msdn,並沒有找到相關的描述。
不過相信在其他庫中,應該還存在其他的類似問題,這裡友情提醒大家在編碼的時候多加留意。
4.可以把工程的c++ library設成(debug) multithread dll版本就不會有這個問題了。
原本只修改了工程的,所以問題依舊,現在兩邊都修改就沒有問題了。
--------------------next---------------------
不行麼?想不通阿,據我的經驗這是明顯的兩份crt的問題,由於靜態聯編crt導致操作file的函式在實際執行時有exe中的和dll中的兩份,又,眾所周知crt依賴於一些全域性的資料,兩份crt必然有兩份資料,比如file和handle的對應關係表之類的,用其中乙份開啟乙個檔案,只能在一處留下記錄,呼叫另一處的fread,這個file*肯定是非法的
解決方法一樓小明說得有理,不是利用mt,而是要那個dll,就是動態聯編crt,於是無論如何,程序中只會有乙個msvcrt.dll,一些需要的全域性資料也只有乙份了
類似的比如exe和dll傳遞c++物件的也可用類似方法解決
此法敝人屢試不爽,不知為何這次不行,著實想不通
不知樓主是否exe和dll都是動態聯編crt的,僅僅一邊動態聯編也是不行的
--------------------next---------------------
兩個指標相減
原文 如果兩個指標指向同乙個陣列,它們就可以相減,其結果為兩個指標之間的元素數目。假設我住在廣場路124號,mag住在廣場路142號,每家之間的位址間距是2 在我這一側用連續的偶數作為街道位址 那麼mag家就在我家往前 142 124 2家,也就是說可以得到我們兩家之間相隔8家。也就是說可以利用兩個...
C指標兩個疑惑
1.cpp view plain copy include include intmain ptr printf d ptr return 0 剛剛看這樣的題目,感覺蠻簡單的。ptr定義指向了 m array的首位址,char型別1位元組。乙個int4個位元組 ptr 後,指標ptr的值加上1乘si...
Dllimport函式時無法在Dll中找到的入口點
今天開發客戶提供的乙個dll時出現無法找到入口點問題,由於客戶也不能明確說明dll,所以一時不知道如何下手,經查詢後找到可通過vs自帶的dumpbin.exe檢視。dumpbin.exe位於 vs的安裝目錄 vc bin下,如果點選dumpbin.exe提示 出現mspdb80.dll無法找到的情況...