You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过成员变量获取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避免重复加载(提升性能),可以调整内存释放时机:

  1. 删除循环内的SDL_FreeSurface(surface)语句
  2. 在主循环结束、销毁foo前,统一调用SDL_FreeSurface(foo->getSurface())

内容的提问来源于stack exchange,提问作者CodeShaman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:13:28