[英]How to properly manage memory (run-time) C++
所以我有一個名為MatrixMxN的類,在構造函數中它具有參數行,列。 我正在嘗試為具有行,列尺寸的2D數組分配內存,盡管這樣做遇到了問題。(我重寫了括號運算符,為每個條目分配值)
{
MatrixMxN coord(4, 1);
coord(0, 0) = 1.0;
coord(0, 1) = 1.0;
coord(0, 2) = 1.0;
coord(0, 3) = 1.0;
}
我面臨的問題似乎是在調用解構函數時收到錯誤:-
Windows已在MatrixTest.exe中觸發了一個斷點。 這可能是由於堆損壞所致,這表明MatrixTest.exe或其已加載的任何DLL中存在錯誤。
我的矩陣類的代碼片段如下:
typedef float* floatPtr;
class MatrixMxN {
private:
float** entry;
int rows;
int cols;
public:
MatrixMxN(int r, int c) {
rows = r;
cols = c;
//Create a matrix
if(rows > 0 && cols > 0) {
//Declare an array of pointers
entry = new floatPtr[rows];
//Declare each array
for(int i=0; i<rows; i++) {
entry[i] = new float[cols];
}
this->empty();
}
}
~MatrixMxN() {
//Free memory
for(int i=0; i<rows; i++) {
delete[] entry[i];
}
//Free pointers array
delete[] entry;
}
void empty() {
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
entry[i][j] = 0;
}
}
}
// Assignment operator
void operator=(MatrixMxN& other) {
//Check they are the same size
assert(rows == other.rows && cols == other.cols);
//Copy
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
entry[i][j] = other(i, j);
}
}
}
float& operator()(const int irow, const int icol) {
//Check they are not out of bounds
assert ( (irow >= 0 && irow < rows) || (icol >= 0 && icol < cols) );
return entry[irow][icol];
}
...
引發錯誤的部分在循環內部的解構函數中;
//Free memory
for(int i=0; i<rows; i++) {
delete[] entry[i];
}
dbgheap.c文件在第一次嘗試刪除[] entry [i]時拋出錯誤,其中i = 0。 盡管在打印矩陣時它可以按預期工作,但是這里似乎有一個錯誤。 希望我在這里提供了足夠的信息,謝謝。
Edit1:包含的賦值運算符重載Edit2:包含的()重載
答:問題是我是以轉置方式而不是如何輸入值。 內存在這里已損壞,感謝所有幫助。
您應該一步步分配內存:分配M * N個浮點數組,然后在每次訪問時計算訪問位置。 您的釋放將同樣簡單:delete []矩陣;
您的課程可能會泄漏內存並具有未定義的行為
那里有一個嚴重的錯誤:您錯過了適當的復制構造函數。 編譯器將為您生成一個正確的代碼:復制指針。 但這不是您想要的。 相反,您的復制構造函數應分配新的內存並復制數組的內容。
換句話說:使用當前的實現,您很容易泄漏內存並進行兩次刪除。
選擇:
std::vector
),這些容器具有定義明確的復制語義並可以自行管理其內存。 當您擁有的只是標准容器時,您甚至根本不需要析構函數,復制構造函數和復制賦值(前提是您不必多態刪除矩陣類) 另外,還有一個風格建議:不要像這樣使用empty
。 所有標准容器都有一個empty()
方法,該方法與您的方法完全不同。
您的empty()方法將遍歷行和行,而不是行和列。 這正在損壞內存,當您刪除條目時會被捕獲。
分配元素時,您可能還會破壞內存,因為在您的示例中索引似乎已轉置:
coord(0, 0) = 1.0;
coord(0, 1) = 1.0;
coord(0, 2) = 1.0;
coord(0, 3) = 1.0;
你不是說:
coord(0, 0) = 1.0;
coord(1, 0) = 1.0;
coord(2, 0) = 1.0;
coord(3, 0) = 1.0;
這可能不是原因,但沒有為MatrixMxN
類定義任何復制構造函數或賦值運算符:定義它們或通過將它們聲明為private
使對象不可復制。
盡管在此示例中不是問題,但是如果rows > 0
但cols <= 0
,則將在析構函數中的未初始化指針上調用delete[]
。 在構造函數中,只有在rows > 0 && cols > 0
, entry
才會被初始化。 如果rows > 0
但cols <= 0
,則析構函數中的以下for
循環仍將調用delete[] entry[i];
:
for(int i=0; i<rows; i++) {
delete[] entry[i]; // entry unitialized
}
其次是:
delete[] entry; // entry unitialized
編輯:
這個在operator()
assert
是不正確的:
assert ( (irow >= 0 && irow < rows) || (icol >= 0 && icol < cols) );
它應該使用&&
:
assert ( (irow >= 0 && irow < rows) && (icol >= 0 && icol < cols) );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.