最近的一個(gè)項(xiàng)目中遇到了調(diào)用別人的sdk接口(dll庫)而傳給我的是一個(gè)vector指針,用完之后還要我來刪除的情況。這個(gè)過程中首先就是在我的exe中將其vector指針轉(zhuǎn)為相應(yīng)指針再獲取vector中相應(yīng)的數(shù)據(jù)問題,始終都獲得不了正確的數(shù)據(jù),要么就是一些非法的數(shù)據(jù);另一個(gè)問題就是delete這個(gè)指針時(shí)候會(huì)產(chǎn)生相應(yīng)異常(針對(duì)這個(gè)問題的思考:如果EXE和DLL都鏈接到DLL的C/C++運(yùn)行期庫,那么代碼將能夠很好地運(yùn)行.但是,如果兩個(gè)模塊中的一個(gè)或者兩個(gè)鏈接到靜態(tài)C/C++運(yùn)行期庫,那delete的操作就會(huì)失敗.)。這叫一個(gè)折騰的糾結(jié)啊 (1)對(duì)于STL,在DLL中使用的時(shí)候,往往存在這些問題,在網(wǎng)絡(luò)上搜集了下,這些都是要平時(shí)使用STL的時(shí)候注意的。 template 是個(gè)好東西啊 . 經(jīng)典的 stl . 強(qiáng)悍的boost. 還有我自己寫的那個(gè) ------- 該死的 ------- 資源管理器.dynamic link也是個(gè)好東西啊. 在windows下叫dll, 在unix下叫so (share object) . 它能省下很多重新發(fā)布軟件帶來的麻煩.但是當(dāng)template 遭遇到dynamic link 時(shí)候, 很多時(shí)候卻是一場(chǎng)惡夢(mèng).現(xiàn)在來說說一部分我已經(jīng)碰到過的問題. 問題主要集中在內(nèi)存分配上.
1> 拿STL來說, 自己寫模板的時(shí)候,很難免就用到stl. stl的代碼都在頭文件里. 那么表示著內(nèi)存分配的代碼.只有包含了它的cpp 編譯的時(shí)候才會(huì)被決定是使用什么樣的內(nèi)存分配代碼. 考慮一下: 當(dāng)你聲明了一個(gè)vector<> . 并把這個(gè)vector<>交給一個(gè) dll里的代碼來用. 用完后, 在你的程序里被釋放了. 那么如果你 在dll里往vector里insert了一些東西. 那么這個(gè)時(shí)候insert 發(fā)生的內(nèi)存分配的代碼是屬于dll的. 你不知道這個(gè)dll的內(nèi)存分配是什么. 是分配在哪里的. 而這個(gè)時(shí)候.釋放那促的動(dòng)作卻不在dll里.....同時(shí). 你甚至無法保證編譯dll的那個(gè)家伙使用的stl版本和你是完全一樣的..> 如此說來, 程序crash掉是天經(jīng)地義的.... 對(duì)策: 千萬別別把你的stl 容器,模板容器在 dll 間傳來傳去 . 記住string也是....
2> 你在dll的某個(gè)類里聲明了一個(gè)vector之類的容器. 而沒有顯式的寫這個(gè)類的構(gòu)造和析構(gòu)函數(shù). 那么問題又來了. 你這個(gè)類肯定有操作這vector的函數(shù). 那么這些函數(shù)會(huì)讓vecoter<>生成代碼. 這些代碼在這個(gè)dll里都是一致的. 但是別忘了.你沒有寫析構(gòu)函數(shù)...... 如果這個(gè)時(shí)候, 別人在外面聲明了一個(gè)這樣的類.然后調(diào)用這個(gè)類的函數(shù)操作了這個(gè)vector( 當(dāng)然使用者并不知道什么時(shí)候操作了vector) . 它用完了這個(gè)類以后. 類被釋放掉了. 編譯器很負(fù)責(zé)的為它生成了一份析構(gòu)函數(shù)的代碼...... 聽好了.這份代碼并不是在 dll里 ... . 事情于是又和1>里的一樣了.... crash ......(可能還會(huì)伴隨著迷茫.....) 對(duì)策: 記得dll里每個(gè)類,哪怕式構(gòu)造析構(gòu)函數(shù)式空的. 也要寫到cpp里去. 什么都不寫也式很糟糕的.....同時(shí),更要把任何和內(nèi)存操作有關(guān)的函數(shù)寫到 .cpp 里...
3> 以上兩個(gè)問題似乎都是比較容易的-----只要把代碼都寫到cpp里去, 不要用stl容器傳來傳去就可以了. 那么第三個(gè)問題就要麻煩的多. 如果你自己寫了一個(gè)模板, 這個(gè)模板用了stl 容器.......... 這個(gè)時(shí)候你該怎么辦呢? 顯然你無法把和內(nèi)存分配相關(guān)的函數(shù)都寫到.cpp里去 . template的代碼都必須放到header file里..... 對(duì)策: 解決這個(gè)問題的基本做法是做一個(gè)stl 內(nèi)存分配器 , 強(qiáng)制把這個(gè)模板里和內(nèi)存分配相關(guān)的放到一個(gè).cpp里去.這個(gè)時(shí)候編譯這個(gè)cpp就會(huì)把內(nèi)存分配代碼固定在一個(gè)地方: 要么是dll. 要么是exe里... 模板+動(dòng)態(tài)鏈接庫的使用問題還很多. 要千萬留心這個(gè)陷阱遍地的東西啊
另外,對(duì)於這種問題的解決辦法,下面3種可行辦法:
1. 傳遞vector指針【注意:事實(shí)證明,這個(gè)也是不行的】
2. 傳遞const vector
3. 儘量不使用stl作為dll間的傳遞參數(shù),使用指針會(huì)更好點(diǎn)
究其原因:是因?yàn)関ector在exe和dll之間傳遞的時(shí)候,由于在dll內(nèi)可能對(duì)vector插入數(shù)據(jù),而這段內(nèi)存是在dll里面分配的,exe無法知道如何釋放內(nèi)存,從而導(dǎo)致問題。而改成const類型后,編譯器便知道dll里不會(huì)改變vector,從而不會(huì)出錯(cuò)?;蛘呖梢哉f這是"cross-DLL problem."(This problem crops up when an object is created using new in one dynamically linked library (DLL) but is deleted in a different DLL)的一種吧。
(2) 從一個(gè)可執(zhí)行程序中輸出模板實(shí)例,在另一個(gè)可執(zhí)行程序中引入此實(shí)例。例如:MyLibrary.DLL將vector <MyClass> 指針回傳給MyProgram.EXE中的一個(gè)函數(shù),需要在MyLibrary.DLL中輸出MyClass類和vector <MyClass> 。在MyProgram.EXE中引入它們后。就可以得到MyLibrary.DLL中靜態(tài)數(shù)據(jù)成員的一份Copy了。 這個(gè)是解決我這個(gè)問題的挺不錯(cuò)的方法,但是并為給予采納和驗(yàn)證。畢竟為了保險(xiǎn)起見最終還是選擇了數(shù)組傳遞數(shù)據(jù),但是還是要給予的原則是誰創(chuàng)建誰釋放。否則還是會(huì)出問題我這里即便是調(diào)用delete[ ]objArray;這里的delete的并不知道要?jiǎng)h除多大的內(nèi)存,而這個(gè)要?jiǎng)h除多大的內(nèi)存信息是在dll中保存著的,那個(gè)dll中的delete才知道。DLL中分配的內(nèi)存DLL要負(fù)責(zé)釋放!(一個(gè)模塊分配的內(nèi)存要在同一個(gè)模塊中釋放?。?/span>
*************************************************************************************************************************** 微軟關(guān)于這類問題的解釋: You may experience an access violation when you access an STL object through a pointer or reference in a different DLL or EXE http://support.microsoft.com/default.aspx?scid=KB;en-us;q172396 How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object http://support.microsoft.com/default.aspx?scid=KB;en-us;q168958
這個(gè)講解也不錯(cuò):http://blog.csdn.net/lewutian/article/details/6786193
STL跨平臺(tái)調(diào)用會(huì)出現(xiàn)很多異常,你可以試試.
STL使用模板生成,當(dāng)我們使用模板的時(shí)候,每一個(gè)EXE,和DLL都在編譯器產(chǎn)生了自己的代碼,導(dǎo)致模板所使用的靜態(tài)成員不同步,所以出現(xiàn)數(shù)據(jù)傳遞的各種問題,下面是詳細(xì)解釋。
原因分析:
在動(dòng)態(tài)連接庫開發(fā)中要特別注意內(nèi)存的分配與釋放問題,稍不注意,極可能造成內(nèi)存泄漏,從而訪問出錯(cuò)。例如在某DLL中存在這樣一段代碼:
|
|