[英]C++ unexpected memory error
我在使用简单的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等。
出乎意料(或由于深夜),当我将空闲行delete [] A或delete插入时,所有内容都会因错误而崩溃(但仍然可以正确打印结果-因此错误必须在此行)。 我试过将其设置为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
}
至少可以通过我在注释中告诉您的方法(或使用调试器)来确定问题。 最简单的方法是改变动态阵列到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[]
-ing时会让人头疼。 现在您可以找出问题所在了,我想...
您在矩阵访问代码中倒置了i和j。
基本上公式可以是
current row + current column * number of rows
要么
current row * number of columns + current column
关于代码和调试的两个说明:
使用一个字母的变量可以最大程度地减少键盘和手指的磨损,并减少磁盘和内存的使用。 但是,它往往会大大增加调试时间。
仅仅因为它不会立即崩溃而使代码正确的假设是绝对错误的。 C / C ++是未定义行为的领域(在您的情况下,可能是最常见的行为:在分配的内存之外进行写操作)。 UB是一件令人讨厌的工作,恰恰是因为它会产生任何结果,(包括(通常)明显没有后果),只会导致完全正确的代码在以后崩溃10.000行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.