繁体   English   中英

与std :: vector的指针无效

[英]Pointer Invalidation with std::vector

我正在编写玩具C ++代码以学习它和游戏开发人员,并沿途包装了SDL。 现在要做的就是加载一个BMP图像并循环显示在屏幕上。 仅发布相关代码。

编辑:我正在将此帖子修订为MVCE。 可以直接找到问题。

#include <SDL.h>
#include <vector>

class Surface {
public:
    Surface(SDL_Surface*);
    ~Surface();
    SDL_Surface* mSurface;
}

Surface::Surface(SDL_Surface* surface) {
    mSurface = surface;
}

Surface::~Surface() {
    SDL_FreeSurface(mSurface);
}

int main(int argc, char* args[])
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        throw("Failed to SDL_Init: " + std::string(SDL_GetError()));
    }

    SDL_Window* window = SDL_CreateWindow("SDL TEST", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 960, SDL_WINDOW_SHOWN);
    SDL_Surface* screenSurface = SDL_GetWindowSurface(window);

    const char * imgPath = "test.bmp";
    std::vector<Surface> surfaces;
    surfaces.push_back(Surface(SDL_LoadBMP(imgPath)));
    SDL_BlitSurface(surfaces.begin()->mSurface, // memory access violation here
                            NULL, screenSurface, NULL);
    SDL_UpdateWindowSurface(window);
    SDL_Delay(2000);

    SDL_Quit();
    return 0;
}

归结为,加载到vectorSurface对象内部的指针变为无效。 我四处阅读,并认为可能与需要一个自定义副本构造函数有关,但是像这样创建一个并不能解决问题:

Surface::Surface(const Surface& other) {
    mSurface = other.mSurface;
    mIsWindowSurface = other.mIsWindowSurface;
}

您没有定义一个复制构造函数,因此使用了默认的复制构造函数,但这并不能满足您的要求。

在行中

 surfaces.push_back(Surface(SDL_LoadBMP(imgPath)));

这是发生了什么:

  1. 创建一个临时SurfacemSurface指针指向新分配的Surface
  2. 使用复制构造函数(或复制分配运算符)将此Surface复制到向量中
  3. 销毁SDL_FreeSurface的临时Surface

然后,当您进入do surfaces.begin()->mSurface, ,您尝试使用已释放的表面。

要在C ++ 11之前解决此问题,您将需要使您的copy-constructor和copy-assignment运算符在语义上进行复制,或者使用引用计数机制来确保仅在没有更多活动指针指向SDL_FreeSurface时才调用SDL_FreeSurface表面。

在C ++ 11中,有许多现成的修复程序; 其中之一是禁用类的复制,并实现move-constructor和move-assignment运算符,和/或使用emplace_back( SDL_LoadBMP ...而不是push_back

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM