From 800c673b62a24faa501939daed55e7563ebf2095 Mon Sep 17 00:00:00 2001 From: Mathias Parnaudeau Date: Thu, 6 May 2021 21:51:23 +0200 Subject: [PATCH] BACKENDS: SDL: Fix memory leak in supported graphics modes Supported graphics modes are grouped in an merged array in which the first part contains modes from the non-OpenGL SDL manager, obtained by a copy dynamically allocated. When the array was rebuilt or aimed to be destroyed, it was only cleared (removing elements) but not freeing duplicated fields name and description. An additional leak came from the temporary array (srcModes) not freed. --- backends/platform/sdl/sdl.cpp | 30 +++++++++++++++++++++++++----- backends/platform/sdl/sdl.h | 9 +++++++-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 6389d9c0f3b..342fd9414e4 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -78,7 +78,7 @@ struct LegacyGraphicsMode { }; // Table for using old names for scalers in the configuration -// to keep compatibiblity with old config files. +// to keep compatibility with old config files. static const LegacyGraphicsMode s_legacyGraphicsModes[] = { { "supereagle2x", "supereagle" }, { "dotmatrix2x", "dotmatrix" }, @@ -112,6 +112,10 @@ OSystem_SDL::OSystem_SDL() OSystem_SDL::~OSystem_SDL() { SDL_ShowCursor(SDL_ENABLE); +#ifdef USE_OPENGL + clearGraphicsModes(); +#endif + // Delete the various managers here. Note that the ModularBackend // destructors would also take care of this for us. However, various // of our managers must be deleted *before* we call SDL_Quit(). @@ -848,17 +852,19 @@ int OSystem_SDL::getGraphicsMode() const { } void OSystem_SDL::setupGraphicsModes() { - _graphicsModes.clear(); + clearGraphicsModes(); _graphicsModeIds.clear(); _defaultSDLMode = _defaultGLMode = -1; // Count the number of graphics modes + const OSystem::GraphicsMode *srcModes; const OSystem::GraphicsMode *srcMode; int defaultMode; GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource, _window); - srcMode = manager->getSupportedGraphicsModes(); defaultMode = manager->getDefaultGraphicsMode(); + srcModes = manager->getSupportedGraphicsModes(); + srcMode = srcModes; while (srcMode->name) { if (defaultMode == srcMode->id) { _defaultSDLMode = _graphicsModes.size(); @@ -866,6 +872,7 @@ void OSystem_SDL::setupGraphicsModes() { _graphicsModes.push_back(*srcMode); srcMode++; } + delete[] srcModes; delete manager; assert(_defaultSDLMode != -1); @@ -881,7 +888,6 @@ void OSystem_SDL::setupGraphicsModes() { srcMode++; } delete manager; - manager = nullptr; assert(_defaultGLMode != -1); // Set a null mode at the end @@ -898,5 +904,19 @@ void OSystem_SDL::setupGraphicsModes() { mode++; } } -#endif +void OSystem_SDL::clearGraphicsModes() { + if (!_graphicsModes.empty()) { + int i = 0; + + OSystem::GraphicsMode *mode = _graphicsModes.begin(); + while (mode->name && i < _firstGLMode) { + free(const_cast(mode->name)); + free(const_cast(mode->description)); + mode++; + i++; + } + _graphicsModes.clear(); + } +} +#endif diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 7eb7d8ba73b..cd95be7b0f4 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -139,7 +139,7 @@ protected: #endif /** - * Initialze the SDL library. + * Initialize the SDL library. */ virtual void initSDL(); @@ -163,10 +163,15 @@ protected: int _defaultGLMode; /** - * Creates the merged graphics modes list + * Create the merged graphics modes list. */ void setupGraphicsModes(); + /** + * Clear the merged graphics modes list. + */ + void clearGraphicsModes(); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; virtual int getDefaultGraphicsMode() const override; virtual bool setGraphicsMode(int mode, uint flags) override;