Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
MallocDebug.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Templates/AlignmentTemplates.h"
7#include "CoreGlobals.h"
8
9class FOutputDevice;
10
11// Debug memory allocator.
12class FMallocDebug : public FMalloc
13{
14 // Tags.
15 enum { MEM_PreTag = 0xf0ed1cee };
16 enum { MEM_PostTag = 0xdeadf00f };
17 enum { MEM_Tag = 0xfe };
18 enum { MEM_WipeTag = 0xcd };
19
20 // Alignment.
21 enum { ALLOCATION_ALIGNMENT = 16 };
22
23 // Number of block sizes to collate (in steps of 4 bytes)
24 enum { MEM_SizeMax = 128 };
25 enum { MEM_Recent = 5000 };
26 enum { MEM_AgeMax = 80 };
27 enum { MEM_AgeSlice = 100 };
28
29private:
30 // Structure for memory debugging.
31 struct FMemDebug
32 {
33 SIZE_T Size;
34 int32 RefCount;
35 int32* PreTag;
38 };
39
41
42 /** Total size of allocations */
44 /** Total size of allocation overhead */
46
47 static constexpr uint32 AllocatorOverhead = sizeof(FMemDebug) + sizeof(FMemDebug*) + sizeof(int32) + ALLOCATION_ALIGNMENT + sizeof(int32);
48
49public:
50 // FMalloc interface.
52 : GFirstDebug( nullptr )
54 , TotalWasteSize( 0 )
55 {}
56
57 /**
58 * Malloc
59 */
60 virtual void* Malloc( SIZE_T Size, uint32 Alignment ) override
61 {
62 check(Alignment <= ALLOCATION_ALIGNMENT && "Alignment currently unsupported in this allocator");
63 FMemDebug* Ptr = (FMemDebug*)malloc( AllocatorOverhead + Size );
64 check(Ptr);
65 uint8* AlignedPtr = Align( (uint8*) Ptr + sizeof(FMemDebug) + sizeof(FMemDebug*) + sizeof(int32), ALLOCATION_ALIGNMENT );
66 Ptr->RefCount = 1;
67
68 Ptr->Size = Size;
71 Ptr->PreTag = (int32*) (AlignedPtr - sizeof(int32));
72 *Ptr->PreTag = MEM_PreTag;
73 *((FMemDebug**)(AlignedPtr - sizeof(int32) - sizeof(FMemDebug*))) = Ptr;
74 *(int32*)(AlignedPtr+Size) = MEM_PostTag;
75 FMemory::Memset( AlignedPtr, MEM_Tag, Size );
76 if( GFirstDebug )
77 {
78 check(GIsCriticalError||GFirstDebug->PrevLink==&GFirstDebug);
80 }
81 GFirstDebug = Ptr;
82 TotalAllocationSize += Size;
84 check(!(PTRINT(AlignedPtr) & ((PTRINT)0xf)));
85 return AlignedPtr;
86 }
87
88 /**
89 * Realloc
90 */
91 virtual void* Realloc( void* InPtr, SIZE_T NewSize, uint32 Alignment ) override
92 {
93 if( InPtr && NewSize )
94 {
95 FMemDebug* Ptr = *((FMemDebug**)((uint8*)InPtr - sizeof(int32) - sizeof(FMemDebug*)));
96 check(GIsCriticalError||(Ptr->RefCount==1));
97 void* Result = Malloc( NewSize, Alignment );
98 FMemory::Memcpy( Result, InPtr, FMath::Min<SIZE_T>(Ptr->Size,NewSize) );
99 Free( InPtr );
100 return Result;
101 }
102 else if( InPtr == nullptr )
103 {
104 return Malloc( NewSize, Alignment );
105 }
106 else
107 {
108 Free( InPtr );
109 return nullptr;
110 }
111 }
112
113 /**
114 * Free
115 */
116 virtual void Free( void* InPtr ) override
117 {
118 if( !InPtr )
119 {
120 return;
121 }
122
123 FMemDebug* Ptr = *((FMemDebug**)((uint8*)InPtr - sizeof(int32) - sizeof(FMemDebug*)));
124
125 check(GIsCriticalError||Ptr->RefCount==1);
126 check(GIsCriticalError||*Ptr->PreTag==MEM_PreTag);
127 check(GIsCriticalError||*(int32*)((uint8*)InPtr+Ptr->Size)==MEM_PostTag);
128
131
133 Ptr->Size = 0;
134 Ptr->RefCount = 0;
135
136 check(GIsCriticalError||Ptr->PrevLink);
137 check(GIsCriticalError||*Ptr->PrevLink==Ptr);
138 *Ptr->PrevLink = Ptr->Next;
139 if( Ptr->Next )
140 {
142 }
143
144 free( Ptr );
145 }
146
147 /**
148 * If possible determine the size of the memory allocated at the given address
149 *
150 * @param Original - Pointer to memory we are checking the size of
151 * @param SizeOut - If possible, this value is set to the size of the passed in pointer
152 * @return true if succeeded
153 */
154 virtual bool GetAllocationSize(void *Original, SIZE_T &SizeOut) override
155 {
156 if( !Original )
157 {
158 SizeOut = 0;
159 }
160 else
161 {
162 const FMemDebug* Ptr = *((FMemDebug**)((uint8*)Original - sizeof(int32) - sizeof(FMemDebug*)));
163 SizeOut = Ptr->Size;
164 }
165
166 return true;
167 }
168
169 /**
170 * Dumps details about all allocations to an output device
171 *
172 * @param Ar [in] Output device
173 */
174 virtual void DumpAllocatorStats( FOutputDevice& Ar ) override
175 {
176 Ar.Logf( TEXT( "Total Allocation Size: %u" ), TotalAllocationSize );
177 Ar.Logf( TEXT( "Total Waste Size: %u" ), TotalWasteSize );
178
179 int32 Count = 0;
180 int32 Chunks = 0;
181
182 Ar.Logf( TEXT( "" ) );
183 Ar.Logf( TEXT( "Unfreed memory:" ) );
184 for( FMemDebug* Ptr = GFirstDebug; Ptr; Ptr = Ptr->Next )
185 {
186 Count += (int32)Ptr->Size;
187 Chunks++;
188 }
189
190 Ar.Logf( TEXT( "End of list: %i Bytes still allocated" ), Count );
191 Ar.Logf( TEXT( " %i Chunks allocated" ), Chunks );
192 }
193
194 /**
195 * Validates the allocator's heap
196 */
197 virtual bool ValidateHeap() override
198 {
199 for( FMemDebug** Link = &GFirstDebug; *Link; Link=&(*Link)->Next )
200 {
201 check(GIsCriticalError||*(*Link)->PrevLink==*Link);
202 }
204 int32 Result = _heapchk();
205 check(Result!=_HEAPBADBEGIN);
206 check(Result!=_HEAPBADNODE);
207 check(Result!=_HEAPBADPTR);
208 check(Result!=_HEAPEMPTY);
209 check(Result==_HEAPOK);
210#endif
211 return( true );
212 }
213
214 virtual bool Exec( UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar ) override
215 {
216 return false;
217 }
218
219 virtual const TCHAR* GetDescriptiveName() override { return TEXT("debug"); }
220
221};
#define check(expr)
#define PLATFORM_WINDOWS
Definition Platform.h:4
#define TEXT(x)
Definition Platform.h:1108
static constexpr uint32 AllocatorOverhead
Definition MallocDebug.h:47
SIZE_T TotalAllocationSize
Definition MallocDebug.h:43
virtual void * Malloc(SIZE_T Size, uint32 Alignment) override
Definition MallocDebug.h:60
virtual bool ValidateHeap() override
FMemDebug * GFirstDebug
Definition MallocDebug.h:40
SIZE_T TotalWasteSize
Definition MallocDebug.h:45
virtual bool GetAllocationSize(void *Original, SIZE_T &SizeOut) override
virtual void * Realloc(void *InPtr, SIZE_T NewSize, uint32 Alignment) override
Definition MallocDebug.h:91
virtual bool Exec(UWorld *InWorld, const TCHAR *Cmd, FOutputDevice &Ar) override
virtual void Free(void *InPtr) override
virtual void DumpAllocatorStats(FOutputDevice &Ar) override
virtual const TCHAR * GetDescriptiveName() override
static FORCEINLINE void * Memset(void *Dest, uint8 Char, SIZE_T Count)