1#if defined(OS_LINUX)
2#include <malloc.h>
3#elif defined(OS_DARWIN)
4#include <malloc/malloc.h>
5#endif
6#include <new>
7
8#include <common/config_common.h>
9#include <common/memory.h>
10#include <Common/MemoryTracker.h>
11
12/// Replace default new/delete with memory tracking versions.
13/// @sa https://en.cppreference.com/w/cpp/memory/new/operator_new
14/// https://en.cppreference.com/w/cpp/memory/new/operator_delete
15#if !UNBUNDLED
16
17namespace Memory
18{
19
20ALWAYS_INLINE void trackMemory(std::size_t size)
21{
22#if USE_JEMALLOC
23 /// The nallocx() function allocates no memory, but it performs the same size computation as the mallocx() function
24 /// @note je_mallocx() != je_malloc(). It's expected they don't differ much in allocation logic.
25 if (likely(size != 0))
26 CurrentMemoryTracker::alloc(nallocx(size, 0));
27#else
28 CurrentMemoryTracker::alloc(size);
29#endif
30}
31
32ALWAYS_INLINE bool trackMemoryNoExept(std::size_t size) noexcept
33{
34 try
35 {
36 trackMemory(size);
37 }
38 catch (...)
39 {
40 return false;
41 }
42
43 return true;
44}
45
46ALWAYS_INLINE void untrackMemory(void * ptr [[maybe_unused]], std::size_t size [[maybe_unused]] = 0) noexcept
47{
48 try
49 {
50#if USE_JEMALLOC
51 /// @note It's also possible to use je_malloc_usable_size() here.
52 if (likely(ptr != nullptr))
53 CurrentMemoryTracker::free(sallocx(ptr, 0));
54#else
55 if (size)
56 CurrentMemoryTracker::free(size);
57#ifdef _GNU_SOURCE
58 /// It's innaccurate resource free for sanitizers. malloc_usable_size() result is greater or equal to allocated size.
59 else
60 CurrentMemoryTracker::free(malloc_usable_size(ptr));
61#endif
62#endif
63 }
64 catch (...)
65 {}
66}
67
68}
69
70/// new
71
72void * operator new(std::size_t size)
73{
74 Memory::trackMemory(size);
75 return Memory::newImpl(size);
76}
77
78void * operator new[](std::size_t size)
79{
80 Memory::trackMemory(size);
81 return Memory::newImpl(size);
82}
83
84void * operator new(std::size_t size, const std::nothrow_t &) noexcept
85{
86 if (likely(Memory::trackMemoryNoExept(size)))
87 return Memory::newNoExept(size);
88 return nullptr;
89}
90
91void * operator new[](std::size_t size, const std::nothrow_t &) noexcept
92{
93 if (likely(Memory::trackMemoryNoExept(size)))
94 return Memory::newNoExept(size);
95 return nullptr;
96}
97
98/// delete
99
100/// C++17 std 21.6.2.1 (11)
101/// If a function without a size parameter is defined, the program should also define the corresponding function with a size parameter.
102/// If a function with a size parameter is defined, the program shall also define the corresponding version without the size parameter.
103
104/// cppreference:
105/// It's unspecified whether size-aware or size-unaware version is called when deleting objects of
106/// incomplete type and arrays of non-class and trivially-destructible class types.
107
108void operator delete(void * ptr) noexcept
109{
110 Memory::untrackMemory(ptr);
111 Memory::deleteImpl(ptr);
112}
113
114void operator delete[](void * ptr) noexcept
115{
116 Memory::untrackMemory(ptr);
117 Memory::deleteImpl(ptr);
118}
119
120void operator delete(void * ptr, std::size_t size) noexcept
121{
122 Memory::untrackMemory(ptr, size);
123 Memory::deleteSized(ptr, size);
124}
125
126void operator delete[](void * ptr, std::size_t size) noexcept
127{
128 Memory::untrackMemory(ptr, size);
129 Memory::deleteSized(ptr, size);
130}
131
132#else
133
134/// new
135
136void * operator new(std::size_t size) { return Memory::newImpl(size); }
137void * operator new[](std::size_t size) { return Memory::newImpl(size); }
138
139void * operator new(std::size_t size, const std::nothrow_t &) noexcept { return Memory::newNoExept(size); }
140void * operator new[](std::size_t size, const std::nothrow_t &) noexcept { return Memory::newNoExept(size); }
141
142/// delete
143
144void operator delete(void * ptr) noexcept { Memory::deleteImpl(ptr); }
145void operator delete[](void * ptr) noexcept { Memory::deleteImpl(ptr); }
146
147void operator delete(void * ptr, const std::nothrow_t &) noexcept { Memory::deleteImpl(ptr); }
148void operator delete[](void * ptr, const std::nothrow_t &) noexcept { Memory::deleteImpl(ptr); }
149
150void operator delete(void * ptr, std::size_t size) noexcept { Memory::deleteSized(ptr, size); }
151void operator delete[](void * ptr, std::size_t size) noexcept { Memory::deleteSized(ptr, size); }
152
153#endif
154