SDL: Fix leaks related to graphics modes

supportedGraphicsModes() now returns to OSystem_SDL a pointer to a deep copy of
surfacesdl's internal graphics mode array. Therefore each can free its
own copy without interfering with the other's.
This commit is contained in:
Eric Culp
2021-03-15 16:48:40 +02:00
committed by Filippos Karapetis
parent ab8dd417a9
commit cbf9072e45
2 changed files with 43 additions and 7 deletions
@@ -77,6 +77,8 @@ const OSystem::GraphicsMode s_supportedStretchModes[] = {
};
#endif
static void initGraphicsModes();
DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Normal (no scaling)", "lowres")
AspectRatio::AspectRatio(int w, int h) {
@@ -170,6 +172,9 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#if SDL_VERSION_ATLEAST(2, 0, 0)
_videoMode.stretchMode = STRETCH_FIT;
#endif
if (!s_supportedGraphicsModes)
initGraphicsModes();
}
SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
@@ -186,6 +191,16 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
free(_currentPalette);
free(_cursorPalette);
delete[] _mouseData;
for (uint i = 0; i < s_supportedGraphicsModes->size() - 1; ++i) {
OSystem::GraphicsMode &gm = (*s_supportedGraphicsModes)[i];
free(const_cast<char *>(gm.name));
free(const_cast<char *>(gm.description));
}
delete s_supportedGraphicsModes;
delete s_supportedGraphicsModesData;
s_supportedGraphicsModes = NULL;
s_supportedGraphicsModesData = NULL;
}
bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
@@ -259,12 +274,8 @@ void static initGraphicsModes () {
for (uint j = 0; j < factors.size(); ++j) {
Common::String n1 = Common::String::format("%s%dx", name, factors[j]);
Common::String n2 = Common::String::format("%s%dx", prettyName, factors[j]);
char *s1 = new char[n1.size()+1];
char *s2 = new char[n2.size()+1];
strcpy(s1, n1.c_str());
strcpy(s2, n2.c_str());
gm.name = s1;
gm.description = s2;
gm.name = strdup(n1.c_str());
gm.description = strdup(n2.c_str());
gm.id = s_supportedGraphicsModes->size();
s_supportedGraphicsModes->push_back(gm);
gmd.scaleFactor = factors[j];
@@ -280,7 +291,20 @@ void static initGraphicsModes () {
const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::supportedGraphicsModes() {
if (!s_supportedGraphicsModes)
initGraphicsModes();
return &(*s_supportedGraphicsModes)[0];
int size = s_supportedGraphicsModes->size();
OSystem::GraphicsMode *modes = new OSystem::GraphicsMode[size];
memcpy(modes, &(*s_supportedGraphicsModes)[0], size * sizeof(OSystem::GraphicsMode));
// Do deep copy. Each can be freed independently of the other.
OSystem::GraphicsMode *gm = modes;
while (gm->name) {
gm->name = strdup(gm->name);
gm->description = strdup(gm->description);
++gm;
}
return modes;
}
const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const {
+12
View File
@@ -153,6 +153,15 @@ OSystem_SDL::~OSystem_SDL() {
delete _mutexManager;
_mutexManager = 0;
#ifdef USE_OPENGL
for (int i = 0; i < _sdlModesCount; ++i) {
// SurfaceSDL needs us to free these
free(const_cast<char *>(_graphicsModes[i].name));
free(const_cast<char *>(_graphicsModes[i].description));
}
delete[] _graphicsModes;
#endif
delete _logger;
_logger = 0;
@@ -939,6 +948,9 @@ void OSystem_SDL::setupGraphicsModes() {
mode->id = i++;
mode++;
}
// SurfaceSDLGraphicsManager expects us to delete[] this
delete[] sdlGraphicsModes;
}
#endif