簡體   English   中英

如何正確管理內存(運行時)C ++

[英]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 > 0cols <= 0 ,則將在析構函數中的未初始化指針上調用delete[] 在構造函數中,只有在rows > 0 && cols > 0entry才會被初始化。 如果rows > 0cols <= 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM