简体   繁体   English

对象破坏时内存泄漏

[英]Memory leak on object destruction

I have a toy project which is a game engine. 我有一个玩具项目,它是一个游戏引擎。 It uses SDL2 and C++11. 它使用SDL2和C ++ 11。 In the code below I tried to make an objects which cleans memory after itself in destructor. 在下面的代码中,我尝试在析构函数中创建一个清除内存的对象。 But something goes wrong and some memory leaks. 但出了问题,一些内存泄漏。 What am I doing wrong? 我究竟做错了什么?

Example is minimal working code which triggers a leak. 示例是触发泄漏的最小工作代码。 I suppose it works like this: Instance of class Game upon costruction creates instances of SDLEngine and Graphics (in this order), both of which allocates some memory too. 我认为它的工作方式如下:类的实例Game on costruction创建了SDLEngineGraphics实例(按此顺序),两者都分配了一些内存。 When game object is destroyed it calls destructors of Graphics and SDLEngine (in this order). game对象被破坏时,它会调用GraphicsSDLEngine析构函数(按此顺序)。 If I add some printing in both of this destructors they are printed in the needed order. 如果我在这两个析构函数中添加一些打印,它们将按所需顺序打印。 But valgrind thinks that memory allocated by SDL_Init() and SDL_CreateWindow() are leaked. 但是valgrind认为由SDL_Init()SDL_CreateWindow()分配的内存被泄露。

Edit: it is probably valgrind behaviour. 编辑:这可能是valgrind的行为。 I saw a similar question and similar warnings in the pretty basic SDL example: Why does valgrind say basic SDL program is leaking memory? 我在相当基本的SDL示例中看到了类似的问题和类似的警告: 为什么valgrind说基本的SDL程序泄漏了内存?

src/leak-test.cpp: SRC /泄漏TEST.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;
}

Makefile: Makefile文件:

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 output: 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)

It turns out this leak belongs to layer under SDL, in the X11 library. 事实证明,这个漏洞属于X11库中的SDL层。 This bug is very old and known by SDL devs. 这个bug很老,SDL开发人员都知道。 See this bugzilla thread: https://bugzilla.libsdl.org/show_bug.cgi?id=2086 看到这个bugzilla线程: https ://bugzilla.libsdl.org/show_bug.cgi id = 2086

I close the question now. 我现在关闭这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM