23
23
#include < chrono>
24
24
#include < thread>
25
25
#include < cstdlib>
26
+ #include < cstddef>
27
+ #if defined(_MSC_VER) && _MSC_VER < 1900
28
+ #define alignof __alignof
29
+ #endif
26
30
27
31
BaseTestMemorySystem::BaseTestMemorySystem () :
28
32
m_currentBytesAllocated(0 ),
@@ -47,11 +51,19 @@ void* BaseTestMemorySystem::AllocateMemory(std::size_t blockSize, std::size_t al
47
51
m_maxBytesAllocated = (std::max)(m_maxBytesAllocated, m_currentBytesAllocated);
48
52
m_totalBytesAllocated += blockSize;
49
53
50
- char * rawMemory = reinterpret_cast <char *>(malloc (blockSize + sizeof (std::size_t )));
54
+ // Note: malloc will always return an address aligned with alignof(std::max_align_t);
55
+ // This alignment value is not always equals to sizeof(std::size_t). But one thing we can make sure is that
56
+ // alignof(std::max_align_t) is always multiple of sizeof(std::size_t).
57
+ // On some platforms, in place construction requires memory address must be aligned with alignof(std::max_align_t).
58
+ // E.g on Mac, x86_64, sizeof(std::size_t) equals 8. but alignof(std::max_align_t) equals 16. std::function requires aligned memory address.
59
+ // To record the malloc size and keep returned address align with 16, instead of malloc extra 8 bytes,
60
+ // we end up with malloc extra 16 bytes.
61
+
62
+ char * rawMemory = reinterpret_cast <char *>(malloc (blockSize + alignof (std::max_align_t )));
51
63
std::size_t *pointerToSize = reinterpret_cast <std::size_t *>(reinterpret_cast <void *>(rawMemory));
52
64
*pointerToSize = blockSize;
53
65
54
- return reinterpret_cast <void *>(rawMemory + sizeof (std::size_t ));
66
+ return reinterpret_cast <void *>(rawMemory + alignof (std::max_align_t ));
55
67
}
56
68
57
69
void BaseTestMemorySystem::FreeMemory (void * memoryPtr)
@@ -62,8 +74,7 @@ void BaseTestMemorySystem::FreeMemory(void* memoryPtr)
62
74
--m_currentOutstandingAllocations;
63
75
}
64
76
65
- std::size_t *pointerToSize = reinterpret_cast <std::size_t *>(memoryPtr);
66
- --pointerToSize;
77
+ std::size_t *pointerToSize = reinterpret_cast <std::size_t *>(reinterpret_cast <char *>(memoryPtr) - alignof (std::max_align_t ));
67
78
std::size_t blockSize = *pointerToSize;
68
79
69
80
ASSERT_GE (m_currentBytesAllocated, blockSize);
0 commit comments