2014-04-12 5 views
3

У меня есть игрушечный проект, который является игровым движком. Он использует SDL2 и C++ 11. В приведенном ниже коде я попытался создать объекты, которые очищают память после себя в деструкторе. Но что-то пошло не так, и некоторые утечки памяти. Что я делаю не так?Утечка памяти при уничтожении объекта

Пример минимального рабочего кода, который вызывает утечку. Я полагаю, что он работает следующим образом: Экземпляр класса Game при построении затрат создает экземпляры SDLEngine и Graphics (в этом порядке), оба из которых также выделяют некоторую память. Когда объект game уничтожен, он называет деструкторы Graphics и SDLEngine (в этом порядке). Если я добавлю некоторую печать в обоих этих деструкторах, они будут напечатаны в необходимом порядке. Но valgrind думает, что память, выделенная SDL_Init() и SDL_CreateWindow(), просочилась.

Редактировать: это, вероятно, поведение valgrind. Я видел подобный вопрос и подобные предупреждения в довольно основной СВД например: 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; 
} 

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 [email protected]) 
    $(CXX) $(CXXFLAGS) $(LDFLAGS) -o [email protected] $^ 

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

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) 
+2

Обратите внимание, что при вводе конструктора деструктор не вызывается. – Jarod42

+0

@ Jarod42: Но в этом случае конструктор позаботится о том, чтобы освободить всю полученную промежуточную память ......., поскольку вызов конструктора не завершен .... –

+0

Похоже, что есть некоторая известная проблема с библиотекой SDL и Valgrind всегда показывает такое сообщение: http://forums.libsdl.org/viewtopic.php?p=42979&sid=8cf1d6c83d4d73fe6cfbb7cbb16b3d28 –

ответ

1

Оказывается, эта утечка относится к слою под SDL, в библиотеке X11. Эта ошибка очень старая и известна разработчикам SDL. См. Эту резьбу bugzilla: https://bugzilla.libsdl.org/show_bug.cgi?id=2086

Закройте вопрос сейчас.

Смежные вопросы