我有一个玩具项目,它是一个游戏引擎。它使用SDL2和C ++ 11。在下面的代码中,我尝试在析构函数中创建一个清除内存的对象。但出了问题,一些内存泄漏。我做错了什么?
示例是触发泄漏的最小工作代码。我想它的工作原理如下:
在构造时类Game
的实例创建了SDLEngine
和Graphics
的实例(按此顺序),两者都分配了一些内存。当game
对象被销毁时,它会调用Graphics
和SDLEngine
的析构函数(按此顺序)。如果我在这两个析构函数中添加一些打印,它们将按所需顺序打印。但是valgrind认为由SDL_Init()
和SDL_CreateWindow()
分配的内存被泄露了。
编辑:这可能是valgrind行为。我在非常基本的SDL示例中看到了类似的问题和类似的警告:Why does valgrind say basic SDL program is leaking memory?
的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;
}
生成文件:
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)
答案 0 :(得分:1)
事实证明,这个漏洞属于X11库中SDL下的层。这个bug很老,SDL开发人员都知道。请参阅此bugzilla线程:https://bugzilla.libsdl.org/show_bug.cgi?id=2086
我现在关闭了这个问题。