[英]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.