【发布时间】:2015-11-02 15:55:10
【问题描述】:
我的代码有点奇怪。我有这个内存泄漏并找到它。根据任务管理器,大约是 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(size of float)*60(times/sec)=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* 数组(在本例中为“matValue”)作为最后一个参数传递给 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 上。
【问题讨论】:
-
我们需要知道
getM做了什么。也许是对unforms.find的调用泄漏了,但是如果不知道这段代码的作用,我们怎么能知道呢? -
@Sputanofono 我建议在 valgrind 中运行您的代码,以获得(真正的)内存泄漏。任务管理器无法向您显示使用
free()返回的内存。 -
这里有很多东西要检查。例如,释放 matValue 是 99% 的错误,因为它应该在 mat4 描述符中释放。是吗?
-
@Sputanofono 在您的 mat4 类中,您还需要非平凡的复制构造函数和赋值运算符(除了析构函数)。如果析构函数有问题,即使调用空函数,内存也会泄漏。您确定 glUniformMatrix4fv 会导致泄漏吗?
-
@Sputanofono 为什么不跳过所有
float* m的东西而只使用std::vector<float> m;?那么很多代码都是多余的,不再需要了。
标签: c++ arrays memory-leaks