Add optional testing utility for malloc/free operations
This commit is contained in:
@@ -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
|
||||
|
||||
60
Source/Engine/Utilities/MallocTester.h
Normal file
60
Source/Engine/Utilities/MallocTester.h
Normal 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;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user