Browse Source

Fixed memory leak when a renderer fails to be created

The supported texture formats were leaking. In order to catch future issues, we'll just do a full teardown of the renderer in the failure case, and make sure it's safe to do so with a partially initialized renderer.
Sam Lantinga 8 months ago
parent
commit
7eb2605630
1 changed files with 27 additions and 17 deletions
  1. 27 17
      src/render/SDL_render.c

+ 27 - 17
src/render/SDL_render.c

@@ -1144,10 +1144,7 @@ error:
 #endif
 
     if (renderer) {
-        SDL_SetObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER, SDL_FALSE);
-
-        SDL_free(renderer->texture_formats);
-        SDL_free(renderer);
+        SDL_DestroyRenderer(renderer);
     }
     return NULL;
 
@@ -5059,10 +5056,15 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
 
     renderer->destroyed = SDL_TRUE;
 
-    SDL_DestroyProperties(renderer->props);
-
     SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
 
+    if (renderer->window) {
+        SDL_PropertiesID props = SDL_GetWindowProperties(renderer->window);
+        if (SDL_GetPointerProperty(props, SDL_PROP_WINDOW_RENDERER_POINTER, NULL) == renderer) {
+            SDL_ClearProperty(props, SDL_PROP_WINDOW_RENDERER_POINTER);
+        }
+    }
+
     SDL_DiscardAllCommands(renderer);
 
     /* Free existing textures for this renderer */
@@ -5072,18 +5074,27 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
         SDL_assert(tex != renderer->textures); /* satisfy static analysis. */
     }
 
-    SDL_free(renderer->vertex_data);
-
-    if (renderer->window) {
-        SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_RENDERER_POINTER);
+    /* Clean up renderer-specific resources */
+    if (renderer->DestroyRenderer) {
+        renderer->DestroyRenderer(renderer);
     }
 
-    /* Free the target mutex */
-    SDL_DestroyMutex(renderer->target_mutex);
-    renderer->target_mutex = NULL;
-
-    /* Clean up renderer-specific resources */
-    renderer->DestroyRenderer(renderer);
+    if (renderer->target_mutex) {
+        SDL_DestroyMutex(renderer->target_mutex);
+        renderer->target_mutex = NULL;
+    }
+    if (renderer->vertex_data) {
+        SDL_free(renderer->vertex_data);
+        renderer->vertex_data = NULL;
+    }
+    if (renderer->texture_formats) {
+        SDL_free(renderer->texture_formats);
+        renderer->texture_formats = NULL;
+    }
+    if (renderer->props) {
+        SDL_DestroyProperties(renderer->props);
+        renderer->props = 0;
+    }
 }
 
 void SDL_DestroyRenderer(SDL_Renderer *renderer)
@@ -5114,7 +5125,6 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
 
     SDL_SetObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER, SDL_FALSE);  // It's no longer magical...
 
-    SDL_free(renderer->texture_formats);
     SDL_free(renderer);
 }