使用std :: vector指针失效

时间:2014-10-15 03:11:07

标签: c++ pointers sdl

我正在编写玩具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;
}

归结为加载到Surface中的vector对象内的指针变为无效。我读过并认为可能与需要自定义复制构造函数有关,但是制作这样的构造函数并没有解决它:

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

1 个答案:

答案 0 :(得分:1)

您没有定义复制构造函数,因此使用了默认的复制构造函数,但这并不是您想要的。

在第

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

这是发生的事情:

  1. 创建一个临时Surface,其mSurface指向新分配的曲面
  2. 使用copy-constructor(或copy-assignment operator)将此Surface复制到向量中
  3. 销毁调用Surface
  4. 的临时SDL_FreeSurface

    然后当你进入surfaces.begin()->mSurface,时,你正在尝试使用已经被释放的表面。

    要在C ++ 11之前修复此问题,您需要使复制构造函数和复制赋值运算符在语义上进行复制,或使用引用计数机制确保SDL_FreeSurface仅被调用一次没有更多活跃的指针到表面。

    在C ++ 11中,还有更多开箱即用的修复程序;其中之一是禁用类的复制,并实现移动构造函数和移动赋值运算符,和/或使用emplace_back( SDL_LoadBMP ...而不是push_back