首页 > 解决方案 > 循环内奇怪的内存泄漏

问题描述

我的工作项目中有内存泄漏问题。实际上,我已经阅读了一些关于内存泄漏的参考资料,发现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;
}

标签: c++

解决方案


该代码与惯用的 C++ 相去甚远。在惯用的 C++中new,并delete没有在您的代码中使用。而不是new[]anddelete[]你应该使用std::vector,这将消除内存泄漏。而不是 new Tanddelete你应该使用std::make_unique<T>().

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

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()


推荐阅读