通过成员变量获取IMG_Load时,SDL_CreateTextureFromSurface二次调用崩溃
SDL_CreateTextureFromSurface二次调用触发段错误的原因与修复
调试过程中,第二次调用SDL_CreateTextureFromSurface时触发段错误(SEGFAULT)。本质原因是第一次循环中释放了类成员变量保存的SDL_Surface内存,导致后续循环中获取的是悬空指针;而直接调用IMG_Load或让方法直接返回IMG_Load结果时,每次都会重新加载新的Surface,因此不会出错。
报错代码示例
#include <SDL.h> #include <SDL_image.h> class Foo { SDL_Surface* _surface; public: SDL_Surface* getSurface() { return _surface; } void setSurface(SDL_Surface* surface) { _surface = surface; } }; int main() { SDL_Init(SDL_INIT_VIDEO); IMG_Init(IMG_INIT_PNG); SDL_Window* window = SDL_CreateWindow("foo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); Foo* foo = new Foo(); foo->setSurface(IMG_Load("img.png")); bool quit = false; SDL_Event e; while(!quit) { SDL_SetRenderDrawColor(renderer,100,0,0,0); SDL_RenderClear(renderer); SDL_Surface* surface = foo->getSurface(); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_FreeSurface(surface); SDL_DestroyTexture(texture); SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); while(SDL_PollEvent( &e ) != 0) { if (e.type == SDL_QUIT) { quit = true; } } } delete foo; SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); IMG_Quit(); SDL_Quit(); return 0; }
规避错误的修改方式
修改Foo类,让getSurface每次返回新加载的Surface:
class Foo { public: SDL_Surface* getSurface() { return IMG_Load("img.png"); } };
直接在循环内加载的正常代码
另一种可行方式是直接在循环内调用IMG_Load:
SDL_SetRenderDrawColor(renderer,100,0,0,0); SDL_RenderClear(renderer); SDL_Surface* surface = IMG_Load("img.png"); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_FreeSurface(surface); SDL_DestroyTexture(texture); SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window);
补充优化方案
如果想复用SDL_Surface避免重复加载(提升性能),可以调整内存释放时机:
- 删除循环内的
SDL_FreeSurface(surface)语句 - 在主循环结束、销毁
foo前,统一调用SDL_FreeSurface(foo->getSurface())
内容的提问来源于stack exchange,提问作者CodeShaman
相关产品推荐
相关产品推荐

