簡體   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