2015-11-02 105 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