2015-01-14 29 views
1

我已經與易C題++程序,發現在給定的矩陣的最大子矩陣:C++意外的內存錯誤

int *A = new int[n*m]; 
... setting fields for matrix, finding the largest one and etc 
... r := size of square-submatrix, max_i := row, max_j := column of the largest 
for (i = max_i; i < max_i + r; i++) 
{ 
    for (j = max_j; j < max_j + r; j++) 
     cout << A[i * n + j] << "\t"; 

     cout << "\n"; 
} 
<memory free> 
end of program 

一切的偉大工程(所以這不是問題的邏輯) - 找到正確的子矩陣,prinitng等。當我把內存中的空行刪除時,意外地(或由於深夜)刪除[] A或刪除所有壓縮的內容(但它仍然正確地打印結果 - 所以錯誤必須在這一行中)。我試過把它設置爲NULL和每個組合。出了什麼問題?

在此先感謝

編輯:

#include <iostream> 
#include <cstdlib> 

using namespace std; 

int main() 
{ 
int i,j,k; 

int m,n; 
int r; 

cout << "Size of matrix: \nRows: "; 
cin >> n; 
cout << "Columns: "; 
cin >> m; 

int *A = new int[n*m]; 

for (i = 0; i < n; i++) 
{ 
    for (j = 0; j < m; j++) 
    { 
     A[n*i + j] = rand() % 19 - 9; 
     cout << A[n*i + j] << "\t"; 
    } 

    cout << "\n"; 
} 


cout << "Size of submatrix: "; 
cin >> r; 

int liczba_kwadratow = (m + 1 -r) * (n+1 -r); 

int max = -10000; 
int max_i = 0; 
int max_j = 0; 

int row_iter = 0; 
int col_iter = 0; 

for (k = 0; k <liczba_kwadratow; k++) 
{ 
    int sum = 0; 
    for (i = row_iter; i < row_iter + r; i++) 
     for (j = col_iter; j < col_iter + r; j++) 
      sum += A[i * n + j];  

    if (sum > max) 
    { 
     max = sum; 
     max_i = row_iter; 
     max_j = col_iter; 
    } 

    col_iter++; 
    if (row_iter + r > m) 
    { 
     row_iter++; 
     col_iter = 0; 
    } 

} 

cout << "Field of the largest submatrix " << r << " of " << r << " equals " << max << "\n"; 

for (i = max_i; i < max_i + r; i++) 
{ 
    for (j = max_j; j < max_j + r; j++) 
     cout << A[i * n + j] << "\t"; 

    cout << "\n"; 
} 

...works great without delete[] A or delete A 

} 
+0

有沒有機會給A [-1]寫信? – drescherjm

+0

我不這麼認爲。我已經發布了代碼。謝謝! – lemoid

+1

使用一些'assert'來確保你沒有執行任何out-of-bound訪問,或者更好的方法是使用at()的'std :: vector'和成員函數'執行訪問。這樣,如果你試圖訪問越界,就會拋出一個異常(如果你簡單地使用'std :: vector :: operator []')這個**不是這種情況)。如果你使用這樣的矢量,可以很容易地測試發生了什麼。作爲一般規則,您應該嘗試避免在現代C++中使用原始指針。 – vsoftco

回答

1

的問題至少可以通過方法(S)我告訴你在評論(或者通過使用調試器)來識別。最簡單的方法是將動態數組更改爲std::vector,然後使用成員函數at。然後你會發現你得到一個出界異常的位置拋出:

for (i = 0; i < n; i++) 
{ 
    for (j = 0; j < m; j++) 
    { 
     A.at(n*i + j) = rand() % 19 - 9; // throws here!!!!, replace n by m 
     cout << A.at(n*i + j) << "\t"; 
    } 

    cout << "\n"; 
} 

當輸入爲6 5 3,那麼你會得到一個異常,當你第一次嘗試訪問A[30],它給你一個頭痛的時候delete[] - 荷蘭國際集團。現在你可以弄清楚我猜的是什麼...

+0

當然,這是問題所在。感謝您的時間和幫助 - 看起來我太累了,無法區分n和m。 順便說一句 - 用這種老式的C語言教學C++有什麼意義? – lemoid

+1

@lemoid在我看來絕對沒有意義,應該從一開始就用現代C++開始學習,即學習標準庫和它的使用的最佳實踐。 – vsoftco

+0

是的 - 這很傷心,但有些導師甚至博士教C++ + C++ + ,類(沒有基本的類和結構之間的區分)和新/刪除 - 有時他們仍然使用malloc!毫無疑問,知道這樣一個低級別的內存管理是很好的,但我同意 - 我不明白使用C++來做這種事情的一個重點。乾杯! – lemoid

1

你在你的矩陣訪問代碼中反轉了i和j。

基本公式可以

current row + current column * number of rows 

current row * number of columns + current column 

您的代碼和調試的兩點注:使用單字母變量

  1. 最大限度地減少了磨損和撕裂你的鍵盤和手指,並減少磁盤和內存的使用。不過,它往往會大大增加調試時間。

  2. 只是因爲它沒有立即崩潰就假定代碼正常是完全錯誤的。 C/C++是未定義行爲的領域(在你的情況下,可能是最常見的行爲:寫入外部分配的內存)。 UB是一件令人討厭的工作,恰恰是因爲它可以產生任何結果,包括(經常)顯然沒有後果,僅僅導致完美的一點代碼在以後損壞10.000行。