内存泄漏导致加载纹理,尽管在渲染函数后调用glDeleteTextures

时间:2015-02-20 16:40:24

标签: c++ opengl memory memory-leaks textures

我正在使用我编写的类加载纹理,如下所示。目的是创建一个新纹理,使用存储在数组中的数据加载它,并将其渲染到屏幕上。创建纹理时没有任何问题,也可以加载。但是,它导致内存泄漏,应用程序内存大小不断增加,尽管调用delete以调用Texture类的析构函数来删除纹理。

void renderCurrentGrid(){    

// Get the current grid (custom wrapper class, it's working fine)
Array2D<real_t> currentGrid = m_Continuum->getCurrentGrid();

// load it as a texture
Texture *currentGridTexture = new Texture(GL_TEXTURE_2D);
currentGridTexture->load(currentGrid.sizeWd(), currentGrid.sizeHt(), &currentGrid(0,0));

......

delete currentGridTexture;
}

纹理类'加载函数:

bool Texture::load(const size_t width, const size_t height, const float *data)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

// Allocate a texture name
glGenTextures(1, &m_TextureObj);

// select current texture
glBindTexture(GL_TEXTURE_2D, m_TextureObj);

// select replace to ensure texture retains each texel's colour
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

// if texture wraps over at the edges
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glGenerateMipmap(GL_TEXTURE_2D);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,/* &density(0,0)*/data);

m_Loaded = true;
return true;
}

和Texture类的析构函数:

Texture::~Texture()
{
glBindTexture(m_TextureTarget, m_TextureObj);
glDeleteTextures(1, &m_TextureObj);
glBindTexture(m_TextureTarget, NULL);
}

Texture class'私有数据成员:

private:
GLenum m_TextureTarget;
GLuint m_TextureObj;

bool m_Loaded;

在这里,我创建了新纹理,并使用纹理类的加载函数加载它。纹理渲染绝对正常,但加载会导致内存泄漏。当我在任务管理器上检查时,应用程序内存大小不断增加。

但是,当我注释掉这行

currentGridTexture->load(....);

内存泄漏停止。我省略了渲染函数,这与问题无关。

1 个答案:

答案 0 :(得分:0)

我设法解决了上面的问题。在Texture类的加载函数中,我正在调用

glGenTextures(1, &m_TextureObj)

调用此函数时,根据OpenGL documentation,第二个参数指定一个数组,其中存储生成的纹理名称。为了存储纹理,它分配了一定量的CPU内存。

每次渲染更新都会调用load函数,因此每次在该函数中调用glGenTextures时,OpenGL都会分配资源。虽然析构函数调用glDeleteTextures,理论上应该释放资源,但根据link,情况并非如此,引用如下:

  

仅仅因为你告诉OpenGL你已经完成了一个纹理对象并不意味着OpenGL必须立即放弃那个内存。这样做通常需要一些非常重量级的操作。因此,司机会将此推迟到以后。

当我在每次更新时创建和删除纹理时,我想出了一个解决方案,以便我可以使用相同的纹理对象,并使用不同的数据加载它,以防止OpenGL在每次更新时分配资源。

我将glGenTextures函数移动到了Texture类的构造函数,因此在实例化Texture对象时只调用它一次。我现在创建一个纹理对象,并在每次更新时使用新数据加载它。

为了确保只调用glGenTextures函数一次,我还在渲染函数中移动了实例化和删除Texture对象,即

Texture *currentGridTexture = new Texture(GL_TEXTURE_2D);
...
delete currentGridTexture;

并将currentGridTexture声明为呈现类的私有数据成员,并在构造函数中对其进行实例化,并在该类的析构函数中将其删除,以便在该类中仅创建和删除一个纹理对象。运行我的应用程序的时间,而不是每次更新时创建和删除纹理对象。