CustomMemoryHook.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Utils/CustomMemoryHook.h>
  6. #if defined(_DEBUG) && !defined(JPH_DISABLE_CUSTOM_ALLOCATOR) && !defined(JPH_COMPILER_MINGW)
  7. // Global to turn checking on/off
  8. static bool sEnableCustomMemoryHook = false;
  9. // Local to temporarily disable checking
  10. static thread_local int sDisableCustomMemoryHook = 1;
  11. // Local to keep track if we're coming through the custom allocator
  12. static thread_local bool sInCustomAllocator = false;
  13. // Struct to put on the stack to flag that we're in the custom memory allocator
  14. struct InCustomAllocator
  15. {
  16. InCustomAllocator()
  17. {
  18. JPH_ASSERT(!sInCustomAllocator);
  19. sInCustomAllocator = true;
  20. }
  21. ~InCustomAllocator()
  22. {
  23. JPH_ASSERT(sInCustomAllocator);
  24. sInCustomAllocator = false;
  25. }
  26. };
  27. // Add a tag to an allocation to track if it is aligned / unaligned
  28. static void *TagAllocation(void *inPointer, size_t inAlignment, char inMode)
  29. {
  30. if (inPointer == nullptr)
  31. return nullptr;
  32. uint8 *p = reinterpret_cast<uint8 *>(inPointer);
  33. *p = inMode;
  34. return p + inAlignment;
  35. }
  36. // Remove tag from allocation
  37. static void *UntagAllocation(void *inPointer, size_t inAlignment, char inMode)
  38. {
  39. if (inPointer == nullptr)
  40. return nullptr;
  41. uint8 *p = reinterpret_cast<uint8 *>(inPointer) - inAlignment;
  42. JPH_ASSERT(*p == inMode);
  43. *p = 0;
  44. return p;
  45. }
  46. static void *AllocateHook(size_t inSize)
  47. {
  48. JPH_ASSERT(inSize > 0);
  49. InCustomAllocator ica;
  50. return TagAllocation(malloc(inSize + 16), 16, 'U');
  51. }
  52. static void *ReallocateHook(void *inBlock, size_t inOldSize, size_t inNewSize)
  53. {
  54. JPH_ASSERT(inNewSize > 0);
  55. InCustomAllocator ica;
  56. return TagAllocation(realloc(UntagAllocation(inBlock, 16, 'U'), inNewSize + 16), 16, 'U');
  57. }
  58. static void FreeHook(void *inBlock)
  59. {
  60. InCustomAllocator ica;
  61. free(UntagAllocation(inBlock, 16, 'U'));
  62. }
  63. static void *AlignedAllocateHook(size_t inSize, size_t inAlignment)
  64. {
  65. JPH_ASSERT(inSize > 0 && inAlignment > 0 && inAlignment <= 64);
  66. InCustomAllocator ica;
  67. return TagAllocation(_aligned_malloc(inSize + 64, inAlignment), 64, 'A');
  68. }
  69. static void AlignedFreeHook(void *inBlock)
  70. {
  71. InCustomAllocator ica;
  72. _aligned_free(UntagAllocation(inBlock, 64, 'A'));
  73. }
  74. static int MyAllocHook(int nAllocType, void *pvData, size_t nSize, int nBlockUse, long lRequest, const unsigned char * szFileName, int nLine) noexcept
  75. {
  76. JPH_ASSERT(!sEnableCustomMemoryHook || sDisableCustomMemoryHook <= 0 || sInCustomAllocator);
  77. return true;
  78. }
  79. void RegisterCustomMemoryHook()
  80. {
  81. Allocate = AllocateHook;
  82. Reallocate = ReallocateHook;
  83. Free = FreeHook;
  84. AlignedAllocate = AlignedAllocateHook;
  85. AlignedFree = AlignedFreeHook;
  86. _CrtSetAllocHook(MyAllocHook);
  87. }
  88. void EnableCustomMemoryHook(bool inEnable)
  89. {
  90. sEnableCustomMemoryHook = inEnable;
  91. }
  92. bool IsCustomMemoryHookEnabled()
  93. {
  94. return sEnableCustomMemoryHook;
  95. }
  96. DisableCustomMemoryHook::DisableCustomMemoryHook()
  97. {
  98. sDisableCustomMemoryHook--;
  99. }
  100. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  101. {
  102. sDisableCustomMemoryHook++;
  103. }
  104. #else
  105. DisableCustomMemoryHook::DisableCustomMemoryHook()
  106. {
  107. }
  108. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  109. {
  110. }
  111. #endif // _DEBUG && !JPH_DISABLE_CUSTOM_ALLOCATOR && !JPH_COMPILER_MINGW