[英]C++ Struct with pointers : constructor and destructor
我遇到一個模擬程序的問題,該程序調用DLL來執行優化任務。 在研究了這個問題一段時間之后,我認為我的問題在於我在DLL返回所需信息后用來釋放內存的析構函數。 仿真程序是在Borland C ++ Builder v6上開發的,DLL是在MS Visual C ++ 2005上開發的。
對於模擬程序(P)和DLL來交換數據,我創建了兩個結構InputCPLEX
和OutputCPLEX
以及一個帶有兩個參數的函數optimize
:一個InputCPLEX
類型的對象和一個OutputCPLEX
類型的OutputCPLEX
。 這兩種結構都在一個頭文件中聲明structures.h
這屬於P項目和DLL項目。
InputCPLEX
和OutputCPLEX
結構都有int
和int*
成員,因此基本上文件structures.h
看起來像:
//structures.h
struct InputCPLEX{
public:
int i;
int* inputData;
}
struct OutputCPLEX{
public:
int j;
int* outputData;
}
我的想法是沿着模擬過程(P的執行),我定期調用DLL來解決優化問題,所以inputData
是與我的優化問題中的變量對應的數組, outputData
是我的變量的最佳值數組。 我知道使用STL容器比較容易,例如vector<int>
,但如果我錯了,請糾正我 - 似乎很難在兩個不同的編譯器之間交換STL對象。
以下是我的主文件中的內容(在P中):
//main.h
InputCPLEX* input;
OutputCPLEX* output;
int* var;
int* sol;
//main.cpp
[...] //lots of code
input = new InputCPLEX;
output = new OutputCPLEX;
int n = X; //where X is an integer
var = new int[n];
[...] //some code to fill var
input->i = n;
input->inputData = var;
optimize(input,output); //calls the DLL
int m = output->j;
sol = new int[n];
sol = output->outputData;
[...] //some code to use the optimized data
delete[] var;
delete[] sol;
delete input;
delete output;
[...] //lots of code
一年多以來,我一直在文件structures.h
沒有任何構造函數或析構函數使用此代碼,因此沒有執行結構成員的初始化。 你可能已經猜到了,我不是C ++的專家,事實上它恰恰相反。 我還想強調一點,我沒有編寫大部分模擬程序,只是一些函數,這個程序是由幾個開發人員開發了10多年,結果非常混亂。
但是,直到最近,一切都運轉良好。 我決定向DLL提供更多信息(用於優化目的),因此在運行大型模擬(涉及大型數據集)時,模擬程序已經系統地崩潰。 額外的信息是兩種結構中的指針,我的猜測是程序泄漏了內存,所以我嘗試編寫構造函數和析構函數,以便可以正確管理分配給結構input
和output
的內存。 我嘗試了以下代碼,我發現在互聯網上搜索:
//structures.h
struct InputCPLEX{
public:
int i;
int* inputData;
int* inputData2; // extra info
int* inputData3; // extra info
InputCPLEX(): i(0), inputData(0), inputData2(0), inputData3(0) {}
~InputCPLEX(){
if (inputData) delete inputData;
if (inputData2) delete inputData2;
if (inputData3) delete inputData3;
}
}
struct OutputCPLEX{
public:
int j;
int* outputData;
int* outputData2;
int* outputData3;
OutputCPLEX(): j(0), outputData(0), outputData2(0), outputData3(0) {}
~OutputCPLEX(){
if (outputData) delete outputData;
if (outputData2) delete outputData2;
if (outputData3) delete outputData3;
}
}
但它似乎不起作用:程序在很短的時間后崩潰得更快。 有人可以幫我識別代碼中的問題嗎? 我知道可能有其他因素影響我的程序的執行,但是如果我刪除了structures.h
文件中的structures.h
函數和析構函數,那么模擬程序仍然可以執行小型模擬,涉及小數據集。
大衛,非常感謝你的幫助。
你必須使用一致的新方法 - 刪除。 如果new[]
獲取了某些內容,則應通過delete[]
刪除它,如果是new
- > delete by delete
。 在您的代碼中,您可以通過new
創建input
和output
,但通過delete[]
。
順便說一句,你不必在刪除前檢查指針為零。 delete
處理零指針沒有問題。
我在你的代碼中看到了幾個問題:
1)內存泄漏/雙重刪除:
sol = new int[n];
sol = output->outputData;
在這里,你在初始化之后立即覆蓋sol
指針,並且new int[n]
分配的數據被泄露。 你也可以在sol
雙重刪除指針 - 在output
析構函數中第二次。 var
的相同問題 - 你通過顯式delete[]
和input
析構函數刪除它兩次。
添加了帶delete
析構函數后,會出現雙刪除問題,看起來就像它沒有問題。
另外,正如@Riga所提到的,你使用new[]
來分配數組,但是在析構函數中delete
而不是delete[]
。 這是不正確的,這是未定義的行為。 盡管這看起來不像崩潰的原因。 在現實世界中,大多數編譯器對內置和POD類型實現delete
和delete[]
沒有區別。 只有delete
具有非平凡析構函數的對象數組時,才會出現嚴重問題。
2)在哪里分配output->outputData
? 如果在DLL中它是另一個問題,因為如果它是在用另一個編譯器實現的DLL中分配的話,通常無法安全地釋放主程序中的內存。 原因是不同的new/delete
實現和主程序和DLL的運行時使用的不同堆。
你總是應該在同一側分配/釋放內存。 或者使用一些常見的低級API - 例如具有相同堆句柄的VirtualAlloc()/VirtualFree()
或HeapAlloc()/HeapFree()
。
這看起來很奇怪:
int m = output->j;
sol = new int[n];
sol = output->outputData;
據我所知,你返回m的大小但是用n分配然后你通過將指針(sol)設置為outputData來覆蓋數組我認為你的意思是這樣的:
int m = output->j;
sol = new int[m];
memcpy(sol,output->outputData,sizeof(int)*m);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.