SDL2如何实现图片仅单次加载 避免内存泄漏按需显示
问题根源
你的代码出现内存泄漏是三个核心错误导致的:
- C语言函数参数为值传递,你在
Display_nosignal函数内部给Scene指针赋值,修改的只是函数栈上的局部副本,不会改变外部传入的指针实际值。因此每次调用函数时Scene == NULL的判断永远成立,会反复执行IMG_LoadTexture创建新纹理,旧纹理既没有被复用也没有被销毁,持续占用内存造成泄漏。 - 你把资源加载逻辑放在了逐帧调用的渲染函数中,本身就违反了SDL资源管理的基本原则:纹理等GPU资源应该在初始化阶段统一加载,渲染阶段只做绘制调用,退出阶段统一销毁。
- 额外逻辑错误:原代码中
SDL_SetRenderTarget(Rendu, Scene);属于API误用,IMG_LoadTexture加载的纹理默认是静态不可绘制的,不能作为渲染目标使用,这行代码会直接触发SDL运行错误,需要删除。
可行实现方案
整体按照「初始化预加载-渲染时仅绘制-退出时统一销毁」的逻辑改造即可,完全避免重复加载问题。
1. 初始化阶段预加载所有常驻纹理
在SDL渲染器创建完成后、进入游戏主循环之前,把电视需要用到的无信号图、枪击场景图全部加载到内存,纹理指针统一存储(可以放在全局变量,也可以放在自定义的游戏状态结构体中,避免散落在各个渲染函数里)。
// 纹理指针统一存储,示例用全局变量,实际项目建议放到游戏上下文结构体中 SDL_Texture* tex_tv_nosignal = NULL; SDL_Texture* tex_tv_shoot = NULL; // 初始化阶段调用,传入已经创建完成的渲染器 int LoadTVTextures(SDL_Renderer* Rendu) { tex_tv_nosignal = IMG_LoadTexture(Rendu, "mages/No_Signal.jpg"); if (tex_tv_nosignal == NULL) { printf("加载无信号纹理失败: %s\n", SDL_GetError()); return -1; } // 后续要切换的枪击场景也在此处提前加载 tex_tv_shoot = IMG_LoadTexture(Rendu, "mages/shoot_scene.jpg"); if (tex_tv_shoot == NULL) { printf("加载枪击场景纹理失败: %s\n", SDL_GetError()); return -1; } return 0; }
2. 渲染函数仅负责绘制,不处理资源加载
渲染函数只接收已经加载完成的纹理指针,执行拷贝绘制逻辑即可,不要在函数内做任何资源创建、销毁操作。切换电视显示内容时,只需要更换传入的纹理指针,没有任何重复加载开销。
// 传入当前要显示的电视纹理、渲染器、电视屏幕在窗口上的目标区域 void DrawTVScreen(SDL_Texture* current_tv_tex, SDL_Renderer* Rendu, const SDL_Rect* dest_rect) { // 仅做绘制,无资源操作 SDL_RenderCopy(Rendu, current_tv_tex, NULL, dest_rect); }
- 常态显示时传入
tex_tv_nosignal即可,需要切换到枪击场景时直接传入预加载好的tex_tv_shoot,切换过程无IO、无内存分配。
3. 程序退出时统一销毁资源
在游戏退出流程中、SDL渲染器销毁之前,统一释放所有预加载的纹理,避免退出时的资源泄漏。
void UnloadTVTextures() { if (tex_tv_nosignal != NULL) { SDL_DestroyTexture(tex_tv_nosignal); tex_tv_nosignal = NULL; } if (tex_tv_shoot != NULL) { SDL_DestroyTexture(tex_tv_shoot); tex_tv_shoot = NULL; } }
注意事项
- 绝对不要在逐帧执行的主循环逻辑中调用
IMG_LoadTexture、SDL_CreateTexture这类资源创建接口,不仅会造成内存泄漏,磁盘IO和GPU资源创建的开销还会导致严重的帧率卡顿。 - 如果后续需要新增更多电视播放的画面,统一在初始化加载阶段加入即可,切换逻辑不需要修改。
- 只有通过
SDL_CreateTexture创建时指定了SDL_TEXTUREACCESS_TARGET标志的纹理,才能作为SDL_SetRenderTarget的目标使用,外部加载的图片纹理不要做此操作。
内容的提问来源于stack exchange,提问作者dMight
相关产品推荐
相关产品推荐

