C ++内存泄漏浮点指针

时间:2015-11-02 15:55:10

标签: c++ arrays memory-leaks

我的代码在这里有些奇怪。我发现了这个内存泄漏并找到了它。根据任务经理的说法,大约4KB /秒。这段代码每秒被调用60次。

void Shader::setUniform(std::string uniformName, mat4 value){
    float* matValue = value->getM();
    glUniformMatrix4fv(uniforms.find(uniformName)->second, 1, GL_TRUE, matValue);
    free(matValue);
}

作为4x4矩阵,它是一个包含16个浮点数的浮点数*。每秒60次泄漏16(tiems)* 4(浮动大小)* 60(次/秒)= 3840字节。它适合任务经理说的。问题是,为什么这里有内存泄漏?

我试着评论第3行,而且泄漏已经不存在了。因此,似乎获取数组并删除它并不会泄漏内存,但调用glUniformMatrix4fv()可以。为什么会这样?我没有线索。

我的矩阵类是这样的:

class mat4{
    public:
    mat4();
    mat4(const mat4& orig);
    virtual ~mat4();
    mat4* initIdentity();
    mat4 operator+(mat4 other);
    mat4 operator+(float value);
    mat4 operator-(mat4 other);
    mat4 operator-(float value);
    mat4 operator*(mat4 other);
    mat4 operator*(float value);
    bool operator==(mat4 other);
    bool operator!=(mat4 other);
    mat4* initTranslation(float x, float y, float z);
    void setM(float* m);
    float* getM() const;
    float get(int row, int col) const;
    void set(float value, int row, int col);
private:
    float* m;
};

实施是:

mat4::mat4(){
    m = (float*)malloc(16*sizeof(float));
}
mat4::mat4(const mat4& orig){
    m = (float*)malloc(16*sizeof(float));
    for(int i=0; i<16; i++)
        m[i] = orig.m[i];
}
mat4::~mat4(){
    free(m);
}
mat4* mat4::initIdentity(){
    m[0]=1;     m[1]=0;     m[2]=0;     m[3]=0;
    m[4]=0;     m[5]=1;     m[6]=0;     m[7]=0;
    m[8]=0;     m[9]=0;     m[10]=1;    m[11]=0;
    m[12]=0;    m[13]=0;    m[14]=0;    m[15]=1;
    return this;
}
mat4* mat4::initTranslation(float x, float y, float z){
    m[0]=1;     m[1]=0;     m[2]=0;     m[3]=x;
    m[4]=0;     m[5]=1;     m[6]=0;     m[7]=y;
    m[8]=0;     m[9]=0;     m[10]=1;    m[11]=z;
    m[12]=0;    m[13]=0;    m[14]=0;    m[15]=1;
    return this;
}
mat4 mat4::operator+(mat4 other){
    mat4 result = mat4();
    for(int i=0; i<16; i++)
        result.m[i] = m[i] + other.m[i];
    return result;
}
mat4 mat4::operator+(float value){
    mat4 result = mat4();
    for(int i=0; i<16; i++)
        result.m[i] = m[i] + value;
    return result;
}
mat4 mat4::operator-(mat4 other){
    mat4 result = mat4();
    for(int i=0; i<16; i++)
        result.m[i] = m[i] - other.m[i];
    return result;
}
mat4 mat4::operator-(float value){
    mat4 result = mat4();
    for(int i=0; i<16; i++)
        result.m[i] = m[i] - value;
    return result;
}
mat4 mat4::operator*(mat4 other){
    mat4 result = mat4();
    for(int i=0; i<4; i++)
        for(int j=0; j<4; j++)
            result.m[i*4+j] = m[4*i+0]*other.m[0*i+j]+
                              m[4*i+1]*other.m[1*i+j]+
                              m[4*i+2]*other.m[2*i+j]+
                              m[4*i+3]*other.m[3*i+j];
    return result;
}
mat4 mat4::operator *(float value){
    mat4 result = mat4();
    for(int i=0; i<16; i++)
        result.m[i] = m[i] * value;
    return result;
}
bool mat4::operator==(mat4 other){
    for(int i=0; i<16; i++)
        if(fabsf(m[i]-other.m[i])<=FLT_EPSILON)
            return false;
    return true;
}
bool mat4::operator!=(mat4 other){
    int numEqual = 0;
    for(int i=0; i<16; i++)
        if(fabsf(m[i]-other.m[i])<=FLT_EPSILON)
            numEqual++;
    if(numEqual == 16)
        return false;
    return true;
}
void mat4::setM(float* m)
{
    free(this->m);
    this->m = m;
}
float* mat4::getM() const{return m;}
float mat4::get(int row, int col) const{return m[row*4+col];}
void mat4::set(float value, int row, int col){m[row*4+col]=value;}

getM()方法是这样的:

float* mat4::getM() const{return m;}

我试着评论一切。只有当我将float *数组(在本例中为#34; matValue&#34;)传递给glUniformMatrix4fv()函数作为最后一个参数时,它才会泄漏内存。

为了更清楚,我发现unifrom为0并尝试了呼叫:

glUnifromMatrix4fv(0, 1, GL_TRUE, matValue);

仍然是内存泄漏。 取消注释所有行没有内存泄漏。即使方法是这样的:

void Shader::setUniform(std::string uniformName, mat4 value){
    glUniformMatrix4fv(0, 1, GL_TRUE, value.getM());
}

它不会泄漏内存的唯一方法是注释掉函数调用:

void Shader::setUniform(std::string uniformName, mat4 value){
    //glUniformMatrix4fv(0, 1, GL_TRUE, value.getM());
}

但我必须打电话给我,所以我绝望了。

在这里,我使用DrMemory,因为我在Windows上。

Link to the leak result by DrMemory

Link to the error result by DrMemory

2 个答案:

答案 0 :(得分:1)

如果使用OpenGL ES 2.0,则根据the documentation of glUniformMatrix4fv(),第三个参数必须为GL_FALSE,否则会生成GL_INVALID_VALUE错误。

Because OpenGL keeps a set of error flags,每次调用glGetError()测试并清除其中一个标志,内存泄漏问题可能是Shader :: setUniform()生成新GL_INVALID_VALUE错误的结果每次都没有清除。

答案 1 :(得分:1)

void Shader::setUniform(std::string uniformName, mat4 value){
    float* matValue = value->getM();
    glUniformMatrix4fv(uniforms.find(uniformName)->second, 1, GL_TRUE, matValue);
    free(matValue);
}

您按值传递mat4。这意味着您将从呼叫者复制mat4。当您复制mat4时,为其分配新内存。然后,您使用getM()获取指向该内存的指针。在使用free() matValue所指向的内存之后,这就是问题开始的地方。 free()将释放value创建的内存。然后value超出范围并调用析构函数。析构函数然后在您已调用free()的指针上调用free(),该指针是未定义的行为。

摆脱free()中对setUniform()的调用,由于setUniform()是一个无效函数,因此您只需要修改副本就无所事事。我相信你的意思是/应该通过引用传递mat4

void Shader::setUniform(std::string uniformName, mat4& value)