這種問題,在編譯的時候是不會出現問題的,但是在運作時就會崩潰,
例如 接口 來至A.dll
#define MAX_LINE 255
struct _ttt
{
_ttt()
{
memset(a,0,MAX_LINE*sizeof(TCHAR));
memset(b,0,MAX_LINE*sizeof(TCHAR));
memset(c,0,MAX_LINE*sizeof(TCHAR));
}
TCHAR a[MAX_LINE];
TCHAR b[MAX_LINE];
TCHAR c[MAX_LINE];
};
typedef CArray<_ttt,_ttt&> CArrayTTT;
extern __declspec(dllexport) void Fun(LPCTSTR pszFilePath, CArrayTTT& arr);
(這裡的pszFilePath 是一個檔案路徑,這個沒什麼問題,arr是傳入在傳出的參數,就是在接口裡面會有資料往裡面添加)
在另外一個exe工程裡調用 A.dll 中的接口Fun
{
CArrayTTT arr;
CString sFilePath = _T("a.txt");
Fun(sFilePath,arr);
}
到這裡應該編譯連接配接都沒問題,但是在運作到這段代碼的時候,出了右邊的大括号就會崩潰,提示在_CrtIsValidHeapPointer函數裡異常,
這說明什麼:說明在釋放局部變量記憶體的時候出現了問題,查找相關資料得知(例如MSDN),dll中的資料堆棧是獨立的,跟目前應用程式是分開的,在目前應用程式中釋放dll中的堆棧空間是不對的,原因就是你把dll堆棧空間中的位址當成目前應用程式中的堆棧空間中的位址了,這段話說的我也是醉了,慢慢了解吧,反正這樣是不允許的。
如何解決這種問題呢,如果把dll和調用dll的堆棧空間區分開來處理,就不會出現這種問題了,就上面的例子 把 接口改下:我這裡這樣改的(也可以有其他更好的方法來處理)
extern __declspec(dllexport) void Fun(LPCTSTR pszFilePath, CArrayTTT*& pArr);
參數 pArr 的記憶體在dll中申請
void Fun(LPCTSTR pszFIlePath, CArrayTTT*& pArr)
{
.....
pArr = new CArrayTTT();
....
}
當然 申請了記憶體就别忘了釋放
extern __declspec(dllexport) void ReleaseMem( CArrayTTT* pArr);
void ReleaseMem(CArrayTTT* pArr)
{
if(pArr != NULL)
{
delete pArr;
pArr = NULL;
}
}
在調用 Fun接口的應用程式中就得這樣來用了:
{
CArrayTTT* pArr;
CString sFilePath = _T("a.txt");
Fun(sFilePath,pArr);
ReleaseMem(pArr);
}
當然你也可以有其他的方法解決這種問題,隻要思想是對的,問題總能通過不同的方法來處理掉。