1+ /* ****************************************************************************
2+ *
3+ * PROJECT: Multi Theft Auto v1.0
4+ * LICENSE: See LICENSE in the top level directory
5+ * FILE: multiplayer_sa/CMemoryAllocatorDiagnostics.h
6+ * PURPOSE: Memory allocator diagnostic logging system
7+ *
8+ * Multi Theft Auto is available from https://www.multitheftauto.com/
9+ *
10+ *****************************************************************************/
11+
12+ #pragma once
13+
14+ #include < cstddef> // For std::size_t
15+ #include < cstdint> // For std::uintptr_t
16+
17+ namespace mta
18+ {
19+ namespace memory
20+ {
21+ namespace diagnostics
22+ {
23+ // Check if memory allocation debugging should be enabled
24+ // Returns true in debug builds OR when user has enabled EDiagnosticDebug::BAD_ALLOC (#0000 Memory allocation debug) in MTA advanced settings > "Debug setting:"
25+ bool IsMemoryAllocationDebuggingEnabled () noexcept ;
26+
27+ // Core diagnostic logging function
28+ void LogAllocationFailure (const char * reason, void * ptr = nullptr , std::size_t size = 0 , std::size_t alignment = 0 ,
29+ void * caller = nullptr ) noexcept ;
30+
31+ // Specialized logging functions for different failure scenarios
32+ void LogHeapAllocationFailure (const char * reason, void * ptr, std::size_t size, std::size_t alignment, void * caller) noexcept ;
33+ void LogVirtualAllocFailure (const char * reason, void * ptr, std::size_t size, std::size_t alignment, void * caller) noexcept ;
34+ void LogSafetyRejection (const char * reason, void * ptr, std::size_t size, std::size_t alignment, const char * safety_condition,
35+ void * caller) noexcept ;
36+ void LogCriticalSystemFailure (const char * reason, void * ptr, std::size_t size, std::size_t alignment, void * caller) noexcept ;
37+
38+ // Memory pressure analysis
39+ void LogMemoryPressureDetails () noexcept ;
40+ }
41+ }
42+ }
43+
44+ // Conditional compilation macros for diagnostic logging
45+ // These provide zero overhead when diagnostics are disabled
46+ #if defined(MTA_DEBUG) || defined(MTA_ENABLE_DIAGNOSTIC_LOGGING) || defined(DEBUG) || defined(_DEBUG)
47+ #include < intrin.h> // For _ReturnAddress() intrinsic
48+
49+ // Debug builds: always enabled
50+ #if defined(MTA_DEBUG) || defined(DEBUG) || defined(_DEBUG)
51+ #define MTA_MEMORY_LOG_ALLOCATION_FAILURE (reason, ptr, size, alignment ) \
52+ mta::memory::diagnostics::LogAllocationFailure (reason, ptr, size, alignment, _ReturnAddress())
53+
54+ #define MTA_MEMORY_LOG_DEALLOCATION_FAILURE (reason, ptr) \
55+ mta::memory::diagnostics::LogAllocationFailure(reason, ptr, 0 , 0 , _ReturnAddress())
56+
57+ #define MTA_MEMORY_LOG_HEAP_FAILURE (reason, ptr, size, alignment) \
58+ mta::memory::diagnostics::LogHeapAllocationFailure(reason, ptr, size, alignment, _ReturnAddress())
59+
60+ #define MTA_MEMORY_LOG_VIRTUAL_FAILURE (reason, ptr, size, alignment) \
61+ mta::memory::diagnostics::LogVirtualAllocFailure(reason, ptr, size, alignment, _ReturnAddress())
62+
63+ #define MTA_MEMORY_LOG_SAFETY_REJECTION (reason, ptr, size, alignment, condition) \
64+ mta::memory::diagnostics::LogSafetyRejection(reason, ptr, size, alignment, condition, _ReturnAddress())
65+
66+ #define MTA_MEMORY_LOG_CRITICAL_FAILURE (reason, ptr, size, alignment) \
67+ mta::memory::diagnostics::LogCriticalSystemFailure(reason, ptr, size, alignment, _ReturnAddress())
68+
69+ // Release builds: conditional on user setting
70+ #else
71+ #define MTA_MEMORY_LOG_ALLOCATION_FAILURE (reason, ptr, size, alignment ) \
72+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
73+ mta::memory::diagnostics::LogAllocationFailure (reason, ptr, size, alignment, _ReturnAddress ()); } while (0 )
74+
75+ #define MTA_MEMORY_LOG_DEALLOCATION_FAILURE (reason, ptr ) \
76+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
77+ mta::memory::diagnostics::LogAllocationFailure (reason, ptr, 0 , 0 , _ReturnAddress ()); } while (0 )
78+
79+ #define MTA_MEMORY_LOG_HEAP_FAILURE (reason, ptr, size, alignment ) \
80+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
81+ mta::memory::diagnostics::LogHeapAllocationFailure (reason, ptr, size, alignment, _ReturnAddress ()); } while (0 )
82+
83+ #define MTA_MEMORY_LOG_VIRTUAL_FAILURE (reason, ptr, size, alignment ) \
84+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
85+ mta::memory::diagnostics::LogVirtualAllocFailure (reason, ptr, size, alignment, _ReturnAddress ()); } while (0 )
86+
87+ #define MTA_MEMORY_LOG_SAFETY_REJECTION (reason, ptr, size, alignment, condition ) \
88+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
89+ mta::memory::diagnostics::LogSafetyRejection (reason, ptr, size, alignment, condition, _ReturnAddress ()); } while (0 )
90+
91+ #define MTA_MEMORY_LOG_CRITICAL_FAILURE (reason, ptr, size, alignment ) \
92+ do { if (mta::memory::diagnostics::IsMemoryAllocationDebuggingEnabled ()) \
93+ mta::memory::diagnostics::LogCriticalSystemFailure (reason, ptr, size, alignment, _ReturnAddress ()); } while (0 )
94+ #endif
95+
96+ #else
97+ // Release builds without diagnostic support: no-op macros for zero overhead
98+ #define MTA_MEMORY_LOG_ALLOCATION_FAILURE (reason, ptr, size, alignment ) ((void )0 )
99+ #define MTA_MEMORY_LOG_DEALLOCATION_FAILURE (reason, ptr ) ((void )0 )
100+ #define MTA_MEMORY_LOG_HEAP_FAILURE (reason, ptr, size, alignment ) ((void )0 )
101+ #define MTA_MEMORY_LOG_VIRTUAL_FAILURE (reason, ptr, size, alignment ) ((void )0 )
102+ #define MTA_MEMORY_LOG_SAFETY_REJECTION (reason, ptr, size, alignment, condition ) ((void )0 )
103+ #define MTA_MEMORY_LOG_CRITICAL_FAILURE (reason, ptr, size, alignment ) ((void )0 )
104+
105+ #endif // MTA_DEBUG || MTA_ENABLE_DIAGNOSTIC_LOGGING
0 commit comments