我正在编写玩具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;
}
答案 0 :(得分:1)
您没有定义复制构造函数,因此使用了默认的复制构造函数,但这并不是您想要的。
在第
行 surfaces.push_back(Surface(SDL_LoadBMP(imgPath)));
这是发生的事情:
Surface
,其mSurface
指向新分配的曲面Surface
复制到向量中Surface
。SDL_FreeSurface
醇>
然后当你进入surfaces.begin()->mSurface,
时,你正在尝试使用已经被释放的表面。
要在C ++ 11之前修复此问题,您需要使复制构造函数和复制赋值运算符在语义上进行复制,或使用引用计数机制确保SDL_FreeSurface
仅被调用一次没有更多活跃的指针到表面。
在C ++ 11中,还有更多开箱即用的修复程序;其中之一是禁用类的复制,并实现移动构造函数和移动赋值运算符,和/或使用emplace_back( SDL_LoadBMP
...而不是push_back
。