2016-08-02 48 views
0

所以我在我的SDL2.0程序中有一個memeory泄漏 我設法把它弄到這塊代碼, 我不知道我是否只是盲目,但任何人都可以看到他們是否他們在這裏可以看到內存泄漏?SDL 2.0內存泄漏

我感謝任何迴應的人。

SDL_Color colour = { 255,255,255 }; 

SDL_Surface* surfaceMessage = nullptr; 

SDL_Texture* Message = nullptr; 

for (int i = 0; i < m_vItems.size(); i++) 
{ 
    if (surfaceMessage != nullptr) 
    { 
     SDL_FreeSurface(surfaceMessage); 
    } 

    SDL_Color colour = {255,255,255}; 
    if (i == m_iSelection) 
    { 
     colour = { 255,0,0 }; 
    } 

    surfaceMessage = TTF_RenderText_Solid(m_Font, m_vItems[i].c_str(), colour); // as TTF_RenderText_Solid could only be used on SDL_Surface then you have to create the surface first 

    Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage); //now you can convert it into a texture 


    //Get split change 
    float thing = screenHeight - 2 * (screenHeight* 0.3); 
    thing /= m_vItems.size(); 

    SDL_Rect Message_rect; //create a rect 
    Message_rect.x = m_iPosX; //controls the rect's x coordinate 
    Message_rect.y = m_iPosY + (i * thing); // controls the rect's y coordinte 
    Message_rect.w = 0.18* screenWidth; // controls the width of the rect 
    Message_rect.h = 0.08 * screenHeight; // controls the height of the rect 

    SDL_RenderCopy(renderer, Message, NULL, &Message_rect); //you put the renderer's name first, the Message, the crop size(you can ignore this if you don't want to dabble with cropping), and the rect which is the size and coordinate of your texture 
} 

if (surfaceMessage != nullptr) 
{ 
    SDL_FreeSurface(surfaceMessage); 
} 
+0

'Message'是否需要釋放內存? – NathanOliver

+3

@NathanOliver紋理確實需要釋放內存,儘管該函數在技術上被命名爲SDL_DestroyTexture(https://wiki.libsdl.org/SDL_DestroyTexture)。 OP可能是使用'std :: unique_ptr'儘管 – jaggedSpire

+0

@jaggedSpire Cool最好。我從來沒有使用過SDL,因爲它只是一個猜測,因爲它是一個指針,並且浮出水面正在清理。 – NathanOliver

回答

3

紋理需要與SDL_DestroyTexture功能被破壞,而你不這樣做,這是導致內存泄漏。

順便說一句,當您不再需要原始指針時手動調用銷燬函數是容易出錯的(您可以輕鬆地忘記它需要去的情況)並且是不必要的,並帶有美妙的世界資源獲取是初始化(RAII)

確保正確處置獲得的資源實際上是C++中一個相當普遍的要求,它非常適合。您可以通過使用RAII來獲取對象生命週期以管理資源,這樣您就可以將銷燬/釋放代碼放入類的析構函數中,因此當管理資源的對象超出範圍時它會自動執行。這使得異常安全也變得容易,因爲即使在異常情況下也會執行析構函數代碼。

對於你的情況,你需要一個類存儲一個指向創建的SDL對象的指針,然後調用相關的SDL生命週期終止函數來處理你在析構函數中管理的各種對象,所以紋理管理類可能看起來像:

class Texture{ 
SDL_Texture* texture_; 
public: 
    // or simply pass the arguments for texture creation in and create it internally 
    Texture(SDL_Texture* texture) : texture_{texture}{} 
    ~Texture(){ 
     if (texture_ != nullptr){ 
      SDL_DestroyTexture(texture_); 
     } 
    } 

    // ... functions to access texture 
}; 

注意,雖然,你基本上包裹指向與結束一生有特殊要求的資源,而這些要求基本上以撥打免費功能將指針作爲參數,只要它不是空指針即可。

你並不需要做具體的類做that-- unique_ptr設計這個工作,如果你給它一個定製刪除將做到這一點令人欽佩。給定一個unique_ptr自定義刪除器也是一件容易的事情。

如果你有一個函數,指針類型T*作爲其唯一參數,並結束尖銳的物體和相關存儲器的壽命的,它是如此簡單:

#include <memory> 

void shoutFooDestruction(Foo* foo); // my special lifetime ending function 

int main(){ 
    std::unique_ptr<Foo, decltype(&shoutFooDestruction)> ptr{ 
     new Foo(), 
     shoutFooDestruction};  
    ptr.reset(new Foo()); 
} 

這將調用兩次:在生命週期開始時爲原始指針賦予唯一指針,並在unique_ptrreset時調用,並且在復位時爲Foo提供一次,當unique_pointer的生存期結束於main的末尾時調用一次。

See it live on Coliru

一個SDL_Texture等效是:

std::unique_ptr<SDL_Texture, &SDL_DestroyTexture> message{ 
    nullptr, 
    SDL_DestroyTexture}; 

和一個SDL_Surface:

std::unique_ptr<SDL_Surface, &SDL_FreeSurface> surfaceMessage{ 
    nullptr, 
    SDL_FreeSurface}; 

你可以這樣調用的唯一指針reset當你想要SDL提供新的紋理或表面,並且他們會處理任何舊紋理或表面紋理e給你。當函數結束時,unique_ptr s的任何剩餘內容將在unique_ptr超出範圍時使用相同的函數處理。


1.在構造3看見,4

2.與nullptr其價值will not call the provided deleter和同樣爲unique_ptr's destructor的唯一指針調用reset,讓你不如果您沒有任何要刪除的內容,請務必避免刪除電話。

+0

我已經做了一個關於在C風格的界面上使用RAII的更完整的文章:[使用RAII從C風格的API管理資源](http://stackoverflow.com/questions/39176805/using-raii -to-管理資源,從-AC-風格-API) – jaggedSpire