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

将自定义Drawable存入容器后绘制触发段错误的技术求助

段错误原因分析及解决办法

看起来你在绘制按钮时遇到了段错误,结合你的代码,我帮你梳理几个最可能的原因和对应的解决思路:

1. Button类的拷贝构造问题(最常见)

你在循环中创建Button局部实例,然后用push_back把它拷贝到levelButtons容器里。如果Button类内部持有裸指针(比如你传入的&levelTexture),而没有实现正确的拷贝构造函数和赋值运算符,就会触发浅拷贝:多个Button实例会共享同一个levelTexture指针。一旦原levelTexture的生命周期结束(比如它是局部变量,循环结束后被销毁),或者某个实例意外释放了这个指针,后续绘制时访问这个野指针就会直接触发段错误。

解决办法:

  • 方案一:实现深拷贝的拷贝构造
    给Button类手动实现拷贝构造函数和赋值运算符,确保对于levelTexture这类资源,要么创建新的副本(比如调用SDL的纹理复制接口),要么用引用计数来管理资源(比如把levelTexture换成std::shared_ptr<SDL_Texture>)。
  • 方案二:避免拷贝,存储指针
    把levelButtons改成std::vector<std::unique_ptr<Button>>,这样直接存储按钮的指针,不会触发拷贝:
    // 修改容器定义
    std::vector<std::unique_ptr<Button>> levelButtons;
    
    // 循环内创建并添加
    for (int i = 1; i <= 8; i++) {
        for (int j = 0; j < 4; j++) {
            auto btn = std::make_unique<Button>(50, 50, std::bind(&Game::continueGame, this, (j * 8) + i), " " + std::to_string((j * 8) + i), &levelTexture);
            btn->setPosition(50 + (i * 100), 200 + (j * 100));
            levelButtons.push_back(std::move(btn));
        }
    }
    
    // 绘制时
    for (auto& btn : levelButtons) {
        win->draw(*btn);
    }
    

2. win指针失效

如果在执行绘制代码时,win这个窗口指针已经变成了野指针(比如窗口被提前销毁、win指向的内存被释放但没有置空),调用win->draw()就会直接触发段错误。

解决办法:

  • 在绘制前检查win的有效性,比如添加断言:
    assert(win != nullptr && "Window pointer is invalid!");
    
  • 排查代码中是否有提前销毁窗口或者重置win指针的逻辑,确保绘制时win指向有效的窗口对象。

3. levelTexture的生命周期问题

如果levelTexture是局部变量(比如在某个函数内定义,函数结束后就被销毁),那么你传给Button的&levelTexture就会变成野指针。当绘制按钮时,Button尝试访问这个已经被释放的纹理资源,就会触发段错误。

解决办法:

  • 确保levelTexture的生命周期至少和levelButtons一样长,比如把它改成Game类的成员变量,而不是局部变量。
  • 或者用智能指针管理纹理,比如std::shared_ptr<SDL_Texture>,这样即使原变量销毁,只要有Button实例持有这个智能指针,纹理资源就不会被释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:47:39