Add optional testing utility for malloc/free operations

This commit is contained in:
Wojtek Figat
2025-07-27 23:20:06 +02:00
parent 8c51ea511a
commit 354eaac56c
2 changed files with 80 additions and 0 deletions

View File

@@ -206,6 +206,16 @@ void PlatformBase::Exit()
#if COMPILE_WITH_PROFILER
#define TEST_MALLOC 0
#if TEST_MALLOC
#include "Engine/Utilities/MallocTester.h"
MallocTester& GetMallocTester()
{
static MallocTester MallocTest;
return MallocTest;
}
#endif
#define TRACY_ENABLE_MEMORY (TRACY_ENABLE)
void PlatformBase::OnMemoryAlloc(void* ptr, uint64 size)
@@ -213,6 +223,11 @@ void PlatformBase::OnMemoryAlloc(void* ptr, uint64 size)
if (!ptr)
return;
#if TEST_MALLOC
if (GetMallocTester().OnMalloc(ptr, size))
LOG(Fatal, "Invalid mallloc detected for pointer 0x{0:x} ({1} bytes)!\n{2}", (uintptr)ptr, size, Platform::GetStackTrace(3));
#endif
#if TRACY_ENABLE_MEMORY
// Track memory allocation in Tracy
//tracy::Profiler::MemAlloc(ptr, (size_t)size, false);
@@ -248,6 +263,11 @@ void PlatformBase::OnMemoryFree(void* ptr)
// Track memory allocation in Tracy
tracy::Profiler::MemFree(ptr, false);
#endif
#if TEST_MALLOC
if (GetMallocTester().OnFree(ptr))
LOG(Fatal, "Invalid free detected for pointer 0x{0:x}!\n{1}", (uintptr)ptr, Platform::GetStackTrace(3));
#endif
}
#endif

View File

@@ -0,0 +1,60 @@
// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Core/Collections/HashSet.h"
#include "Engine/Platform/Platform.h"
#include "Engine/Platform/CriticalSection.h"
/// <summary>
/// The utility for finding double-free or invalid malloc calls.
/// </summary>
class MallocTester
{
private:
bool _entry = true;
CriticalSection _locker;
HashSet<void*> _allocs;
public:
bool OnMalloc(void* ptr, uint64 size)
{
if (ptr == nullptr)
return false;
bool failed = false;
_locker.Lock();
if (_entry)
{
_entry = false;
if (_allocs.Contains(ptr))
{
failed = true;
}
_allocs.Add(ptr);
_entry = true;
}
_locker.Unlock();
return failed;
}
bool OnFree(void* ptr)
{
if (ptr == nullptr)
return false;
bool failed = false;
_locker.Lock();
if (_entry)
{
_entry = false;
if (!_allocs.Remove(ptr))
{
failed = true;
}
_entry = true;
}
_locker.Unlock();
return failed;
}
};