任何人都可以帮我弄清楚为什么在使用gnuWin32时我的代码中存在运行时错误。当GaussSeidel功能被评论时,错误消失。我尝试了在线GNU GCC v4.8.3编译器,它似乎在那里工作正常。 ideone.com上的C ++ 14给了我运行时错误双重免费或损坏。我附上了我的代码的简单版本,它遭受了这个错误。感谢。
#include <iostream>
#include <cmath>
void GaussSeidel(double** const aa, double* const bb, double* xvec, const int nn, int mm)
{
int i = 0, j = 0;
double *ynew=NULL, *yold=NULL, EE=20.0;
ynew=new double[nn];
yold=new double[nn];
while (mm > 0 && EE>0.00001) {
EE=0.0;
for (i = 0; i < nn; i++) {
yold[i]=ynew[i];
ynew[i] = bb[i] / aa[i][i];
for (j = 0; j < nn; j++) {
if (j == i) continue;
ynew[i] = ynew[i] - (aa[i][j] * xvec[j]/ aa[i][i]);
xvec[i] = ynew[i];
}
if (std::abs(ynew[i]-yold[i])>EE) EE=std::abs(ynew[i]-yold[i]);
}
mm--;
}
std::cout << mm << " " << EE << std::endl;
for (j = 0; j < nn; j++)
xvec[i] = ynew[i];
delete [] ynew;
delete [] yold;
}
int main (void)
{
int i, j;
const int Np=100;
double **Infl=NULL, *Source=NULL, *FpdPhi0=NULL;
Source=new double[Np];
FpdPhi0=new double[Np];
Infl = new double *[Np]; for(i = 0; i < Np; i++) Infl[i] = new double[Np];
for (j=0; j<Np; j++){
for (i=0; i<Np; i++){
if (i==j){
Infl[j][i]=1.0;
}
else {
Infl[j][i]=0.0;
}
}
Source[j]=4.0;
FpdPhi0[j]=0.1;
}
GaussSeidel(Infl, Source, FpdPhi0, Np, 300);
for(i = 0; i < Np; i++) delete [] Infl[i];
delete [] Infl;
delete [] Source;
delete [] FpdPhi0;
return 0;
}
答案 0 :(得分:4)
函数内部的最后一个循环使用i
作为索引,此时可能等于nn
且超出范围。您可能打算使用循环变量j
。
因此,您可以访问xvec
数组范围,这是未定义的行为,可能会在删除之前损坏其他内部定义的数组
答案 1 :(得分:0)
我可以确定可能的贡献者。
ynew和yold都是动态分配的基本类型数组(double)。函数中的第一个动作是在循环中指定yold [i] = ynew [i](其中我从零运行到nn-1)
问题是operator new默认初始化数组的元素。基本类型(double,int,pointers等)的默认初始化实际上使它们没有初始化(除了几个特殊情况,例如静态,当它们被初始化时)。
由于形式“x = y”的赋值在y上执行所谓的右值到左值的转换(复杂的说法是“访问y的值,因此x可以赋予相同的值”)。右值到右值的转换在未初始化的变量上具有未定义的行为。
简而言之:在GaussSeidel()中动态分配数组后,您需要在访问元素值之前初始化它们。
在快速浏览中,我没有发现任何其他涉及未定义行为的明显问题。
我还建议考虑使用std :: vector。而不是直接用运算符new和delete进行修改。