Created
December 20, 2024 02:57
-
-
Save dortamiguel/b3d681a1d2ef37f2c975828d13f44476 to your computer and use it in GitHub Desktop.
function memory leak
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
template <typename... Args> struct function { | |
void (*callable)(void *, Args...) = nullptr; | |
static constexpr u32 MAX_CONTEXT_SIZE = 32; | |
char *context = nullptr; | |
function() : context(new char[MAX_CONTEXT_SIZE]) {} | |
template <typename Type> function(Type _function) : function() { | |
*this = std::move(_function); | |
} | |
template <typename Type> function &operator=(Type _function) { | |
struct Context { | |
Type function; | |
Context(Type function) : function(std::move(function)) {} | |
void invoke(Args... args) { | |
function(args...); | |
} | |
}; | |
static_assert(sizeof(Context) <= MAX_CONTEXT_SIZE, "context size is too small"); | |
new (context) Context(std::move(_function)); | |
callable = [](void *_context, Args... args) { | |
static_cast<Context *>(_context)->invoke(args...); | |
}; | |
return *this; | |
} | |
~function() = default; | |
void operator()(Args... args) { | |
if (callable) { | |
callable((void *)context, args...); | |
} | |
} | |
}; | |
struct thread { | |
void *handle = nullptr; | |
function<> task; | |
thread(function<> &&task) : task(std::move(task)) { | |
#if _WIN64 | |
handle = CreateThread( | |
nullptr, 0, (LPTHREAD_START_ROUTINE)task.callable, (void *)task.context, 0, nullptr | |
); | |
#else | |
handle = malloc(sizeof(pthread_t)); | |
pthread_create( | |
(pthread_t *)handle, nullptr, (void *(*)(void *))task.callable, (void *)task.context | |
); | |
#endif | |
} | |
~thread() { | |
detach(); | |
} | |
void join() { | |
if (!handle) return; | |
#if _WIN64 | |
WaitForSingleObject(handle, INFINITE); | |
#else | |
pthread_join(*(pthread_t *)handle, NULL); | |
#endif | |
detach(); | |
} | |
void detach() { | |
if (!handle) return; | |
#if _WIN64 | |
CloseHandle(handle); | |
#else | |
pthread_detach(*(pthread_t *)handle); | |
free(handle); | |
#endif | |
handle = nullptr; | |
} | |
}; | |
// Usage examples | |
void main() { | |
thread audio_loop([]() { | |
while (!input.exit) { | |
music.update(); | |
} | |
}); | |
// game loop goes here | |
audio_loop.join(); | |
} | |
void Level::async_save() { | |
thread([&]() { save(); }).detach(); | |
} | |
// If I add a destructor to function | |
~function() { | |
if (context) { | |
delete[] context; | |
} | |
} | |
// I get this error | |
/* | |
thread main_font_load([&]() { main_font.load("source_code_pro_regular.ttf"); }); | |
thread emoji_font_load([&]() { emoji_font.load("noto_emoji_regular.ttf"); }); | |
thread japanese_font_load([&]() { japanese_font.load("noto_sans_jp_regular.ttf"); }); | |
main_font_load.join(); | |
emoji_font_load.join(); | |
japanese_font_load.join(); | |
================================================================= | |
==80797==ERROR: AddressSanitizer: attempting double-free on 0x00013863ad20 in thread T5: | |
#0 0x125175c88 in wrap__ZdaPv+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x61c88) | |
#1 0x1046e976c in thread::~thread() base.cpp:292 | |
#2 0x1047de7a0 in Fonts::load() font.cpp:127 | |
#3 0x19d37ef90 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x6f90) | |
#4 0x19d379d30 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1d30) | |
0x00013863ad20 is located 0 bytes inside of 32-byte region [0x00013863ad20,0x00013863ad40) | |
freed by thread T5 here: | |
#0 0x125175c88 in wrap__ZdaPv+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x61c88) | |
#1 0x1047de778 in Fonts::load() font.cpp:123 | |
#2 0x19d37ef90 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x6f90) | |
#3 0x19d379d30 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1d30) | |
previously allocated by thread T5 here: | |
#0 0x125175874 in wrap__Znam+0x74 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x61874) | |
#1 0x1047de700 in Fonts::load() font.cpp:123 | |
#2 0x19d37ef90 in _pthread_start+0x84 (libsystem_pthread.dylib:arm64e+0x6f90) | |
#3 0x19d379d30 in thread_start+0x4 (libsystem_pthread.dylib:arm64e+0x1d30) | |
Thread T5 created by T0 here: | |
#0 0x12515fd6c in wrap_pthread_create+0x54 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x4bd6c) | |
#1 0x1046e950c in thread::thread(function<>&&) base.cpp:279 | |
#2 0x10499c7a4 in main main.cpp:72 | |
#3 0x19cff60dc (<unknown module>) | |
SUMMARY: AddressSanitizer: double-free (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x61c88) in wrap__ZdaPv+0x74 | |
==80797==ABORTING | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment