SDL 2.0内存泄漏

时间:2016-08-02 18:32:56

标签: c++ memory-leaks sdl-2

所以我的SDL2.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);
}

1 个答案:

答案 0 :(得分:3)

需要使用SDL_DestroyTexture函数销毁纹理,并且您没有这样做,这会导致内存泄漏。

顺便提一下,当你不再需要它时,在原始指针上手动调用destroy函数是容易出错的(你很容易忘记它需要去的情况)并且没有必要,有了资源获取的美妙世界初始化(RAII)

确保正确处理获得的资源实际上是C ++中相当普遍的要求,并且它非常适合。您可以使用RAII来获取对象生存期来管理资源,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
};

请注意,您实际上是将指针包装到具有非典型生命周期结束要求的资源,并且这些要求本质上是调用一个将指针作为参数的自由函数,前提是它和#39;不是空指针。

你不需要制作一个特定的课程 - unique_ptr 为这项工作设计了,如果你给它一个自定义的删除器,它将会令人钦佩。给unique_ptr自定义删除器也很容易。 1

如果你有一个函数,它将指针类型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());
}

这将调用shoutFooDestruction两次:一次用于在其生命周期开始时给予唯一指针的原始指针,并在unique_ptrreset时调用,一次用于当unique_pointer的生命周期在main结束时,Foo在重置时提供。 2

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};

当您需要SDL中的新纹理或曲面时,您会在唯一指针上调用reset,并且它们会为您处理任何旧纹理或曲面。当unique_ptr超出范围时,函数末尾的unique_ptr s的任何剩余内容将使用相同的函数处理。

1。如构造函数3和4中所见on cppreference's page on constructors for unique pointers

2。在reset上使用nullptr为其值will not call the provided deleter调用<?php include 'config.php'; try { $pdo = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); } catch (PDOException $e) { error_log("PDO connection failed in " . __FILE__ . ", Error: " . $e->getMessage()); die("Database error, please contact administrator"); } $playerEmail = $_REQUEST["playerEmail"]; $sql = "SELECT EMAIL, DATEOFSIGNUP, USERNAME, GENDER, JOB, LVL, HP_NOW, HP_MAX, MANA_NOW, MANA_MAX, STR, SPD, INTEL, XP_NOW, XP_NEEDED, GOLDS, NUMBERSOFITEMS, LOCATION_X, LOCATION_Y FROM players WHERE EMAIL = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$playerEmail]); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode(array("result"=>$result)); ,同样适用于unique_ptr's destructor,因此您无需担心避免删除调用如果您没有要删除的内容。