循环内发生奇怪的内存泄漏

时间:2018-09-06 07:54:03

标签: c++

我的工作项目中存在内存泄漏问题。实际上,我已经阅读了一些有关内存泄漏的参考资料,然后发现每个new应该是delete,但是不幸的是,当循环还没有结束时,我无法删除指针。那我需要解决这个问题的建议。

主程序:

#include <iostream>
#include <iomanip>
#include "linspace.h"
#include "matrik.h"
#include "vektor.h"
#include "FV.h"

using namespace std;
matrik WENO5CPLFRK3(matrik w, double aumax, double dx, double dt, int Ne, int Nt);

int main()
{
    double CFL, tm, t;
    CFL = 0.5;
    tm = 1;
    t = .0;


    int Ne, Np;
    Ne = 1000;
    Np = Ne + 1;

    int Ng, Nt;
    Ng = 3;
    Nt = Ne + Ng + Ng;

    double lb, rb, dx;
    vektor x(Np);
    matrik w(3, Ne);
    matrik q(3, Ne), qn(3, Ne), qm(3, Ne);
    matrik dF(3, Ne);
    double aumax, dt;
    lb = 0.;
    rb = 1.;
    dx = (rb - lb)/Ne;

    x = linspace(lb, rb, Np);
    w = initial(x, Ne);
    aumax = soundspeedmax(w, Ne);
    dt = CFL*dx/aumax;

    int iter = 0;

    while (t < tm){
        cout << "Iteration: "<< ++iter << endl;
        w = WENO5CPLFRK3(w,aumax,dx,dt,Ne,Nt);
        t += dt;
        aumax = soundspeedmax(w, Ne);
        dt = CFL*dx/aumax;
//        cout << t<< endl;
    }

    for (int i = 0; i < Ne; i++){
        cout <<setprecision(10) << w[0][i] << "," << setprecision(3) << w[1][i] << "," << setprecision(3) << w[2][i] << endl;
    }

    return 0;
}

matrik WENO5CPLFRK3(matrik w, double aumax, double dx, double dt, int Ne, int Nt)
{
    matrik dF(3, Ne), qn(3, Ne), q(3, Ne);

    qn = Q(w, Ne);

    dF = WENO5LFCMP(w, aumax, dx, Ne, Nt);
//
    q = qn - dt*dF;
    w = W(q, Ne);
    dF = WENO5LFCMP(w, aumax, dx, Ne, Nt);

    q = 0.75*qn + 0.25*(q - dt*dF);
    w = W(q, Ne);
    dF = WENO5LFCMP(w, aumax, dx, Ne, Nt);

    q = (qn + 2.*(q - dt*dF))/3.;
    w = W(q, Ne);
    return w;
}

我发现dF是内存泄漏的原因。 这是我的WENO5LFCMP函数:

matrik WENO5LFCMP(matrik w, double aumax, double dx, int Ne, int Nt)
{
    int r = 3;
    int Ng = (Nt - Ne)/2;
    matrik wb(3, Nt);
    matrik q(3, Nt);

    wb = boundary(w, Ne, Ng);
    q = Q(wb, Nt);

    double ql[Nt][3], qr[Nt][3];

    for (int i = r - 1; i < Nt - r + 1; i++){
        for (int k = 0; k < 3; k++){
            for (int j = - 2; j < 3; j++){
                v[j + 2] = q[k][i - j];
            }
            vc = WENO5(v);
            ql[i+1][k] = vc[1];
            qr[i][k] = vc[0];
        }
    }
    delete[] vc;

    double** Flux = new double*[Ne + 1];
    for(int j = 0; j < Ne + 1; j++){
        Flux[j] = new double[3];
    }

    for (int i = r; i < Nt-r+1; i++){
        Flux[i -r] = LFFlux(ql[i], qr[i], aumax);
    }

    matrik dF(3, Ne);

    for (int i = 0; i < Ne; i++){
        for (int j = 0; j < 3; j++){
            dF[j][i] = (Flux[i + 1][j] - Flux[i][j])/dx;
        }
    }

    for(int j = 0; j < Ne + 1; j++){
        delete[] Flux[j];
    } delete[] Flux;

    return dF;

}

编辑:matrik标头:

#ifndef MATRIK_H_INCLUDED
#define MATRIK_H_INCLUDED

class matrik
{
private:
    int rows, columns;
    double** src;

public:
    matrik();
    matrik(int ROWS, int COLS);
    matrik(const matrik&);
    ~matrik();

double* operator[](int i) const { return src[i]; }
double& operator()(int i, int j) { return src[i][j]; }

matrik& operator=(const matrik&);
matrik& operator+=(const matrik&);
matrik& operator-=(const matrik&);

friend matrik operator+(const matrik&, const matrik&);
friend matrik operator-(const matrik&, const matrik&);
friend matrik operator*(double, const matrik&);
friend matrik operator*(const matrik&, double);
friend matrik operator/(double, const matrik&);
friend matrik operator/(const matrik&, double);

};

#endif // OVERLOADING_H_INCLUDED

实现:

#include <iostream>
#include "matrik.h"

using namespace std;

matrik::matrik()
{
    src = 0;
    columns = rows = 0;
}

matrik::matrik(int m, int n)
{
    rows = m;
    columns = n;

    src = new double*[rows];
    for (int i = 0; i < rows; i++){
        src[i] = new double[columns];
    }
}

matrik::matrik(const matrik& M)
{
    rows = M.rows;
    columns = M.columns;

    src = new double*[rows];

    for (int i = 0; i < rows; i++){
        src[i] =  new double[columns];
        for (int j = 0; j < columns; j++) src[i][j] = M[i][j];
    }
}

inline matrik::~matrik()
{
    for(int i = 0; i < rows; i++) delete[] src[i];
    delete[] src;
}

matrik& matrik::operator=(const matrik& M)
{
    if (this != &M){
        if (rows != M.rows || columns != M.columns){
            //
        }
        for (int i = 0; i < rows; i++){
            for (int j = 0; j < columns; j++){
                src[i][j] = M[i][j];
            }
        }
    }
    return *this;
}

1 个答案:

答案 0 :(得分:2)

代码与惯用的C ++相距甚远。在惯用的C ++中,newdelete不在您的代码中使用。您应该使用new[]代替delete[]std::vector,这将消除内存泄漏。应当使用new T代替deletestd::make_unique<T>()

话虽如此,即使您保留newdelete,代码也有几个问题。例如,看一下循环:

for (int i = r - 1; i < Nt - r + 1; i++){
    for (int k = 0; k < 3; k++){
        for (int j = - 2; j < 3; j++){
            v[j + 2] = q[k][i - j];
        }
        vc = WENO5(v);  // <--- allocation
        ql[i+1][k] = vc[1];
        qr[i][k] = vc[0];
    }
}
delete[] vc;

最后的delete[] vc表示内存是在较早的分配中分配的:

        vc = WENO5(v);

但是由于分配在循环中,因此delete[] vc也应该在循环中。否则,将来的迭代将丢失先前的vc值,这将泄漏内存。

我希望matrik::operator=中丢失的代码片段在大小不匹配的情况下重新分配内存,并且这样做不会泄漏。


我不能承受太多压力-如果可以避免,请不要使用动态内存分配。留给写std::vector和至少std::make_unique()的专业人士。