我的代码在这里有些奇怪。我发现了这个内存泄漏并找到了它。根据任务经理的说法,大约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上。
答案 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)