1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Fix remaining memory leaks caused by API misuse

This commit is contained in:
Ivan Savenko
2025-04-28 13:55:57 +03:00
parent c0fb1d1b3b
commit 554a414302
6 changed files with 17 additions and 8 deletions

View File

@@ -57,6 +57,7 @@
#include "LobbyClientNetPackVisitors.h" #include "LobbyClientNetPackVisitors.h"
#include <vcmi/events/EventBus.h> #include <vcmi/events/EventBus.h>
#include <SDL_thread.h>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
@@ -114,9 +115,13 @@ void CServerHandler::threadRunNetwork()
} }
catch (const TerminationRequestedException &) catch (const TerminationRequestedException &)
{ {
// VCMI can run SDL methods on network thread, leading to usage of thread-local storage by SDL
// Such storage needs to be cleaned up manually for threads that were not created by SDL
SDL_TLSCleanup();
logGlobal->info("Terminating network thread"); logGlobal->info("Terminating network thread");
return; return;
} }
SDL_TLSCleanup();
logGlobal->info("Ending network thread"); logGlobal->info("Ending network thread");
} }

View File

@@ -410,7 +410,7 @@ void InputHandler::dispatchMainThread(const std::function<void()> & functor)
SDL_Event event; SDL_Event event;
event.user.type = SDL_USEREVENT; event.user.type = SDL_USEREVENT;
event.user.code = 0; event.user.code = 0;
event.user.data1 = static_cast <void*>(heapFunctor.get()); event.user.data1 = nullptr;
event.user.data2 = nullptr; event.user.data2 = nullptr;
SDL_PushEvent(&event); SDL_PushEvent(&event);
@@ -426,9 +426,6 @@ void InputHandler::handleUserEvent(const SDL_UserEvent & current)
if (!dispatchedTasks.try_pop(task)) if (!dispatchedTasks.try_pop(task))
throw std::runtime_error("InputHandler::handleUserEvent received without active task!"); throw std::runtime_error("InputHandler::handleUserEvent received without active task!");
if (current.data1 != task.get())
throw std::runtime_error("InputHandler::handleUserEvent received unknown pointer!");
(*task)(); (*task)();
} }

View File

@@ -373,6 +373,11 @@ FFMpegStream::~FFMpegStream()
avcodec_free_context(&codecContext); avcodec_free_context(&codecContext);
avformat_close_input(&formatContext); avformat_close_input(&formatContext);
// for some reason, buffer is managed (e.g. reallocated) by FFmpeg
// however, it must still be freed manually by user
if (context->buffer)
av_free(context->buffer);
av_free(context); av_free(context);
} }

View File

@@ -448,5 +448,6 @@ void SDLImageShared::savePalette()
SDLImageShared::~SDLImageShared() SDLImageShared::~SDLImageShared()
{ {
SDL_FreeSurface(surf); SDL_FreeSurface(surf);
SDL_FreePalette(originalPalette); if (originalPalette)
SDL_FreePalette(originalPalette);
} }

View File

@@ -236,8 +236,8 @@ SDLImageScaler::~SDLImageScaler()
{ {
ENGINE->dispatchMainThread([surface = intermediate]() ENGINE->dispatchMainThread([surface = intermediate]()
{ {
// potentially SDL bug, execute SDL_FreeSurface in main thread to avoid thread races to its internal state // SDL_FreeSurface must be executed in main thread to avoid thread races to its internal state
// may be fixed somewhere between 2.26.5 - 2.30 // will be no longer necessary in SDL 3
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
}); });
} }

View File

@@ -90,7 +90,8 @@ ScalableImageParameters::ScalableImageParameters(const SDL_Palette * originalPal
ScalableImageParameters::~ScalableImageParameters() ScalableImageParameters::~ScalableImageParameters()
{ {
SDL_FreePalette(palette); if (palette)
SDL_FreePalette(palette);
} }
void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette, EImageBlitMode blitMode) void ScalableImageParameters::preparePalette(const SDL_Palette * originalPalette, EImageBlitMode blitMode)