C ++意外的内存错误

时间:2015-01-14 00:33:36

标签: c++

我在easy 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

一切都很好(所以逻辑没问题) - 找到正确的子矩阵,打印等等。

出乎意料地(或由于深夜)当我放入内存空闲行删除[] 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

}

2 个答案:

答案 0 :(得分:1)

问题至少可以通过我在评论中告诉你的方法(或使用调试器)来识别。最简单的方法是将动态数组更改为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[]时遇到麻烦。现在你可以弄清楚我猜错了什么......

答案 1 :(得分:1)

您在矩阵访问代码中反转了i和j。

基本上公式可能是

current row + current column * number of rows

current row * number of columns + current column

关于代码和调试的两个评论:

  1. 使用单字母变量可以最大限度地减少键盘和手指的磨损,并减少磁盘和内存的使用。但是,它会大大增加调试时间。

  2. 假设代码没问题只是因为它没有立即崩溃是完全错误的。 C / C ++是未定义行为的领域(在您的情况下,可能是最常见的行为:在分配的内存之外写入)。 UB是一项令人讨厌的工作,正是因为它可以产生任何结果,包括(经常)明显没有后果,只会导致完全正常的代码在10.000行后崩溃。