[英]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;
}
归结为,加载到vector
的Surface
对象内部的指针变为无效。 我四处阅读,并认为可能与需要一个自定义副本构造函数有关,但是像这样创建一个并不能解决问题:
Surface::Surface(const Surface& other) {
mSurface = other.mSurface;
mIsWindowSurface = other.mIsWindowSurface;
}
您没有定义一个复制构造函数,因此使用了默认的复制构造函数,但这并不能满足您的要求。
在行中
surfaces.push_back(Surface(SDL_LoadBMP(imgPath)));
这是发生了什么:
Surface
其mSurface
指针指向新分配的Surface Surface
复制到向量中 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.