c++ - 对象销毁时内存泄漏

标签 c++ memory-management c++11 memory-leaks sdl

我有一个玩具项目,它是一个游戏引擎。它使用 SDL2 和 C++11。在下面的代码中,我试图创建一个在析构函数中自行清理内存的对象。但是出了点问题,有些内存泄​​漏。我做错了什么?

示例是触发泄漏的最小工作代码。我想它是这样工作的: 类 Game 的实例在构建时创建了 SDLEngineGraphics 的实例(按此顺序),它们都分配了一些内存。当 game 对象被销毁时,它会调用 GraphicsSDLEngine 的析构函数(按此顺序)。如果我在这两个析构函数中添加一些打印,它们将按需要的顺序打印。但是 valgrind 认为 SDL_Init()SDL_CreateWindow() 分配的内存泄漏了。

编辑:这可能是 valgrind 行为。我在非常基本的 SDL 示例中看到了类似的问题和类似的警告:Why does valgrind say basic SDL program is leaking memory?

src/泄漏测试.cpp:

#include <SDL2/SDL.h>
#include <stdexcept>

class SDLEngine {
public:
    SDLEngine() {
        if (SDL_Init(SDL_INIT_VIDEO) != 0) {
            throw std::runtime_error("SDL_Init"); // line 7
        }
        if (SDL_ShowCursor(SDL_DISABLE) < 0) {
            throw std::runtime_error("SDL_ShowCursor");
        }
    }
    ~SDLEngine() {
        SDL_Quit();
    }
};

class Graphics {
public:
    Graphics() :
        sdlWindow{SDL_CreateWindow(
                    "LeakTest",
                    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                    320, 240,
                    0
                    )} // line 27
    {
        if (sdlWindow == nullptr) {
            throw std::runtime_error("SDL_CreateWindow");
        }
    }
    ~Graphics() {
        SDL_DestroyWindow(sdlWindow);
    }
    Graphics(const Graphics&)=delete;
    Graphics& operator=(const Graphics&)=delete;
private:
    SDL_Window *sdlWindow;
};

class Game {
public:
    Game() :
        sdlEngine_(),
        graphics_() // line 46
    {
        SDL_Event event;
        bool running{true};
        while (running) {
            while (SDL_PollEvent(&event)) {
                switch (event.type) {
                case SDL_KEYDOWN:
                    running = false;
                    break;
                default:
                    break;
                }
            }
        }

    }
    ~Game() {}
private:
    const SDLEngine sdlEngine_;
    Graphics graphics_;
};

int main() {
    Game game; // line 70
    return 0;
}

生成文件:

CXX := g++
MKDIR := mkdir -p
CXXFLAGS += `pkg-config --cflags sdl2 SDL2_image`
CXXFLAGS += -Wall -Werror -Wextra -Weffc++ -pedantic -std=c++0x -g
LDFLAGS += `pkg-config --libs sdl2 SDL2_image`
PROG := bin/leak-test
OBJS := $(patsubst src/%.cpp,obj/%.o, $(wildcard src\/*.cpp))
#                         escaped to fool SO parser ^
.PHONY: all clean

all: build

build: $(PROG)

clean:
    rm -rf $(PROG) $(OBJS)

$(PROG): obj/leak-test.o

$(PROG):
    @$(MKDIR) $(dir $@)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^

obj/%.o : src/%.cpp
    @$(MKDIR) $(dir $@)
    $(CXX) $(CXXFLAGS) -c -MD -o $@ $<

Valgrind 输出:

host:cave-test » valgrind --leak-check=full ./bin/leak-test 
==28815== Memcheck, a memory error detector
==28815== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==28815== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==28815== Command: ./bin/leak-test
==28815== 
==28815== 
==28815== HEAP SUMMARY:
==28815==     in use at exit: 66,235 bytes in 506 blocks
==28815==   total heap usage: 19,844 allocs, 19,338 frees, 44,931,400 bytes allocated
==28815== 
==28815== 20 bytes in 2 blocks are definitely lost in loss record 7 of 101
==28815==    at 0x4C274A0: malloc (vg_replace_malloc.c:291)
==28815==    by 0x5BF8829: strdup (strdup.c:42)
==28815==    by 0x7203666: ??? (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x7204474: _XimSetICValueData (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x71FFA69: _XimLocalCreateIC (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x71E6044: XCreateIC (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x5111CD2: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x51120F7: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x51055FF: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x510540F: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x507048E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x400D6E: SDLEngine::SDLEngine() (leak-test.cpp:7)
==28815== 
==28815== 20 bytes in 2 blocks are definitely lost in loss record 8 of 101
==28815==    at 0x4C274A0: malloc (vg_replace_malloc.c:291)
==28815==    by 0x5BF8829: strdup (strdup.c:42)
==28815==    by 0x7203666: ??? (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x7204474: _XimSetICValueData (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x71FFA69: _XimLocalCreateIC (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x71E6044: XCreateIC (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
==28815==    by 0x5111CD2: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x51120F7: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x51055FF: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x400F11: Graphics::Graphics() (leak-test.cpp:27)
==28815==    by 0x401012: Game::Game() (leak-test.cpp:46)
==28815==    by 0x400D31: main (leak-test.cpp:70)
==28815== 
==28815== 104 bytes in 1 blocks are definitely lost in loss record 60 of 101
==28815==    at 0x4C274A0: malloc (vg_replace_malloc.c:291)
==28815==    by 0xD330A11: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==28815==    by 0xD309600: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==28815==    by 0xD305E7A: ??? (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==28815==    by 0xD30660F: glXChooseVisual (in /usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1.2.0)
==28815==    by 0x510ED0E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x510EF40: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x5103B65: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x51056FB: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x510540F: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x507048E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.2.0)
==28815==    by 0x400D6E: SDLEngine::SDLEngine() (leak-test.cpp:7)
==28815== 
==28815== LEAK SUMMARY:
==28815==    definitely lost: 144 bytes in 5 blocks
==28815==    indirectly lost: 0 bytes in 0 blocks
==28815==      possibly lost: 0 bytes in 0 blocks
==28815==    still reachable: 66,091 bytes in 501 blocks
==28815==         suppressed: 0 bytes in 0 blocks
==28815== Reachable blocks (those to which a pointer was found) are not shown.
==28815== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==28815== 
==28815== For counts of detected and suppressed errors, rerun with: -v
==28815== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 7 from 3)

最佳答案

事实证明,此泄漏属于 X11 库中 SDL 下的层。这个错误非常古老,SDL 开发人员都知道。请参阅此 bugzilla 线程:https://bugzilla.libsdl.org/show_bug.cgi?id=2086

我现在关闭问题。

关于c++ - 对象销毁时内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23027862/

相关文章:

c++ - 这段代码如何打印5?

c++ - 如何将接口(interface)对象传递给方法?

c++ - 用于调试 Borland 和 Visual Studio 应用程序的工具

c++ - QInputDialog 在 getDouble() 中显示逗号而不是点

java - 如何增加Jboss中的Heap和Perm内存?

c++ - 如何获得 std::regex 的所有可能匹配项

java - 垃圾收集和线程

c - 如何在 linux 内核中导出 init_mm

c++ - 连接一元参数的模板参数包

c++ - 如何使用 std::transform 为越界写入抛出异常?