【问题标题】:SDL not freeing system RAMSDL 未释放系统 RAM
【发布时间】:2012-08-28 19:46:28
【问题描述】:

我创建这样的纹理:

//Create temp SDL_Surface
SDL_Surface* surface = IMG_Load(this->path.c_str());

//If we successfully loaded an image
if (surface)
{
    SDL_DisplayFormatAlpha(surface);

    bounds = GameRectangle(surface->w, surface->h);

    GLuint object(0);

    glGenTextures(1, &object);

    glBindTexture(GL_TEXTURE_2D, object);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);

    SDL_FreeSurface(surface);

    return object;
}

glDeleteTextures() 会正确释放 VRAM,但系统 RAM 会保留并不断增加,直到游戏崩溃。

我将它定位到 SDL_Surface,显然表面内存没有被释放。

有什么想法吗?

【问题讨论】:

  • 这是操作系统释放 RAM 的工作,因此解决方案可能是特定于操作系统的
  • 我使用的是 Windows 7 Professional 64bit, SP1
  • 您如何测量内存使用情况?请记住,仅查看任务列表可能会给您带来错误的结果 --- SDL 正在释放内存是完全可行的,只是不将其交还给系统(这可能非常困难) .这意味着您不会看到任务列表内存使用量减少,但内存仍可供您的应用程序重用。
  • @DavidGiven “RAM 使用量不断增加,直到游戏崩溃(大约 300mb/级)”表明它确实在泄漏。
  • 我正在使用 Process Explorer,当它达到我的物理内存的大约 90% 并且我加载了一个新级别时,大多数纹理都是白色的,一段时间后它崩溃并给我不同的错误,比如访问冲突或堆栈溢出。

标签: c++ opengl memory sdl ram


【解决方案1】:

这与 OpenGL 无关。

您对 SDL_DisplayFormatAlpha 的调用会返回一个新的 SDL_Surface,因此您的原始表面仍然被分配。这意味着您将泄露每张图片的副本。

你应该这样做:

SDL_Surface* surfaceWithAlpha = SDL_DisplayFormatAlpha(surface);
SDL_FreeSurface(surface);
...rest of code use surfaceWithAlpha 
SDL_FreeSurface(surfaceWithAlpha);

请参阅documentation

【讨论】:

  • 啊,很棒的电话,现在可以完美运行了。它甚至将使用的 RAM 从 300mb 减少到 30mb。谢谢!
  • 我想补充一点,它以某种方式出人意料地工作。如果我在其余代码中使用 surfaceWithAlpha,颜色会失真。因此,我尝试删除 SDL_DisplayFormatAlpha(surface),它在两个第一级工作得很好,但在第三级崩溃,没有给出错误。所以我保留了 SDL_DisplayFormatAlpha(surface) 并在其下方添加了 SDL_FreeSurface(surfaceWithAlpha) ,现在它可以完美运行了。
【解决方案2】:

一开始我没有注意到解决方法对你来说就足够了。

然后,调用glTexImage2D,提供等于0 的纹理大小应该强制OpenGL 释放内存。然后,您可以将其删除。如果它不起作用,则泄漏在您的代码中。

【讨论】:

  • 谢谢,你建议我在哪里调用 glTextImage2D 以及纹理大小是哪个值?现在我在绑定纹理后调用它一次: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
  • opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml 所以我相信它会像(GL_TEXTURE_2D, 0, anything, 0, 0, 0, anything, anything, 0)
  • glTexImage 似乎不会导致复制到 RAM,因为如果我将代码更改为您的示例,所有纹理都会消失,但内存使用量仍在增长。请看一下我添加到原始问题中的 sn-p。
  • 您可以使用一些自定义内存分配器来确保您的代码不会泄漏吗?
  • 我将问题定位到仅用于绑定纹理的 SDL_Surface。显然 SDL_FreeSurface 并没有像我想象的那样释放内存。
猜你喜欢
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2020-10-07
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 2013-10-28
相关资源
最近更新 更多