2015-11-02 9 views
0

Здесь есть что-то странное. У меня эта утечка памяти, и я нашел ее. Это около 4 КБ/сек в соответствии с диспетчером задач. Этот кусок кода называется 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); 
} 

Будучи матрицей 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 * (в данном случае «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, так как я нахожусь на окнах.

Link to the leak result by DrMemory

Link to the error result by DrMemory

+5

Нам нужно знать, что делает 'getM'. Может быть, это вызов 'unforms.find', который протекает, но как мы можем знать, не зная, что делает какой-либо из этого кода? –

+0

3840 байт в секунду не 4 МБ в секунду. Это даже не 4 КБ в секунду. Может быть, '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() испытаний и очищает один из этих флагов, проблема утечки памяти могут быть результат Shader :: setUniform() генерирует новую ошибку GL_INVALID_VALUE каждый раз, что никогда не очищен.

+0

Пробовал, но есть еще утечка. – Sputanofono

+0

[this] (https://www.opengl.org/sdk/docs/man/html/glUniform.xhtml) версия документации не вызывает, что * transpose * должен быть '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(), на котором указано неопределенное поведение.

Избавиться от вызова free() в setUniform() и так setUniform() является функцией аннулируются вы не basiaclly делать ничего, так как вы только копию необходимости модифицировать. Я считаю, что вы хотели/должны были передать mat4 по ссылке:

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

Выполнено, но все еще есть утечка: - / – Sputanofono

Смежные вопросы