二维数组中的C ++错误

时间:2014-03-27 04:48:53

标签: c++ arrays linear-algebra matrix-multiplication

我在使用c ++中的二维数组时遇到了一些内存问题。

摘自主要内容:

int **A,**B,**C;    
A = new int*[d];
B = new int*[d];
C = new int*[d];

if (file.is_open()){
  for (int i = 0; i < d ;i++){
    A[i] = new int[d];
    C[i] = new int[d];
    for(int j = 0; j < d ;j++){
      if(getline(file,line)){
        A[i][j] = atoi(line.c_str());
      }else{
        cout<<"Dimension does not match inputfile.\n";
        return(1);
      }
    }
  }

  for (int i = 0; i < d ;i++){
    B[i] = new int[d];
    for(int j = 0; j < d ;j++){
      if(getline(file,line)){
        B[i][j] = atoi(line.c_str());
      }else{
        cout<<"Dimension does not match inputfile.\n";
        return(1);
      }
    }
  }
  file.close();
}
...
cout<<"A4\n";
PrintM(A,n);
AddMatrix(B,bi,bj,B,bi,bj+n/2,C,ci,cj,n/2);
cout<<"A5\n";
PrintM(A,n);
...

添加矩阵例程:

void AddMatrix(int** X,int ai,int aj,int** Y, int bi,int bj,int** Z,int ci,int cj,int n){
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++) 
      Z[i+ci][j+cj] = X[i+ai][j+aj] + Y[i+bi][j+bj];
}

PrintM例程:

void PrintM(int **P,int n){
  for (int i=0;i<n;i++){
      cout<<"[";
      for (int j=0;j<n;j++){
        if (j != n-1)
          cout<<P[i][j]<<",";
        else
          cout<<P[i][j]<<"]\n";
      }
  }
  cout<<endl;
}

输出:

A4
[0,0]
[0,0]

A5
[4,0]
[0,0]

我不知道为什么在AddMatrix例程中修改数组A,因为我甚至没有在例程调用中使用它。我还没有包含所有代码(300行),但我不能在一个简短的例子中重现这个问题。我没有像在任何地方说A = C那样愚蠢。我无法弄清楚我哪里出错了。

2 个答案:

答案 0 :(得分:0)

书面缓冲区溢出

由于函数正在修改未传递给函数的其他数据,因此在写入时看起来像buffer overflow。函数中唯一的写入是

Z[i+ci][j+cj] = X[i+ai][j+aj] + Y[i+bi][j+bj];

您正在Z之外写入已分配/目的地为A的内存中。你想在Z内写,即你必须检查

  • 0<=i+ci<DZ1DZ1
  • 的第一维Z
  • 0<=j+cj<DZ2DZ2
  • 的第二维Z

现在,ij都在循环中运行,最小0和最大值n-1。对于2i的每个值,必须遵守j不等式,因此我们获得

  • 0<=ci<DZ1-(n-1)DZ1
  • 的第一维Z
  • 0<=cj<DZ2-(n-1)DZ2
  • 的第二维Z

如果已知尺寸DZ1DZ2,请考虑在assert的开头添加AddMatrix(),例如

assert(0<=ci<DZ1-(n-1) && "buffer overrun in the 1st dimension");
assert(0<=cj<DZ2-(n-1) && "buffer overrun in the 2nd dimension");

并在顶部添加#include<cassert>。以上内容将解决A在调用中更改的问题,其中A甚至未作为参数传递。这是Z的缓冲区溢出。

但是,您可能会在XY读取中出现缓冲区溢出。这不会影响A,你会发现你可能在开发的后期有一个bug。

如果您打算长时间或在大型项目中使用此代码,请添加更多断言,检查aiajbibj的范围。

阅读中的缓冲区溢出

另一种可能是对象A小于n n,当您打印A时,实际上是C的一部分打印。检查n的大小是A

答案 1 :(得分:0)

感谢大家的答案,我在代码的不同部分发现了问题。我递归地调用了一个函数,其中A和C是同一个对象。 ** 手腕上的自拍 **