2015-11-02 65 views
0

我的代码在这里有些奇怪。我有这个内存泄漏,并找到它。任务管理器的速度约为4KB /秒。这段代码每秒被调用60次。C++内存泄漏浮点指针

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

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

我试着评论第三行,泄漏不再存在。所以看起来,获取数组并删除它不会泄漏内存,但调用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 *数组(在本例中为“matValue”)作为最后一个参数传递给glUniformMatrix4fv()函数时,才会泄漏内存。

更清晰,我发现高校统战为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

+5

我们需要知道'getM'的作用。也许这是对'unforms.find'的调用泄漏,但是我们怎么知道这些代码不知道什么? –

+0

每秒3840字节不是每秒4MB。它甚至不是每秒4KB。也许'uniforms.find'是罪魁祸首? –

+0

@JonatanHedborg你说得对,我写错了,它是4KB。抱歉。 – Sputanofono

回答

1

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

Because OpenGL keeps a set of error flags,并且每次调用glGetError()测试和清除这些标志之一,内存泄漏问题可能是着色的()产生一个新的GL_INVALID_VALUE错误每次不会被清零时,结果:: setUniform。

+0

尝试过,但仍然有泄漏。 – Sputanofono

+0

[this](https://www.opengl.org/sdk/docs/man/html/glUniform.xhtml)文档的版本并没有调用*转置*必须是'GL_FALSE' – NathanOliver

+0

@NathanOliver OpenGL和[ OpenGL ES 3.0+](https://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml)没有这个限制。 –

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(),其中未定义行为。

得到setUniform()摆脱调用到free()既然setUniform()是你basiaclly什么都不做,因为你只对矫正副本void函数。我相信你的意思是/应该通过引用mat4

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

完成,但仍然有泄漏: - / – Sputanofono