2
0

CustomMemoryHook.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. InCustomAllocator ica;
  49. return TagAllocation(malloc(inSize + 16), 16, 'U');
  50. }
  51. static void FreeHook(void *inBlock)
  52. {
  53. InCustomAllocator ica;
  54. free(UntagAllocation(inBlock, 16, 'U'));
  55. }
  56. static void *AlignedAllocateHook(size_t inSize, size_t inAlignment)
  57. {
  58. JPH_ASSERT(inAlignment <= 64);
  59. InCustomAllocator ica;
  60. return TagAllocation(_aligned_malloc(inSize + 64, inAlignment), 64, 'A');
  61. }
  62. static void AlignedFreeHook(void *inBlock)
  63. {
  64. InCustomAllocator ica;
  65. _aligned_free(UntagAllocation(inBlock, 64, 'A'));
  66. }
  67. static int MyAllocHook(int nAllocType, void *pvData, size_t nSize, int nBlockUse, long lRequest, const unsigned char * szFileName, int nLine) noexcept
  68. {
  69. JPH_ASSERT(!sEnableCustomMemoryHook || sDisableCustomMemoryHook <= 0 || sInCustomAllocator);
  70. return true;
  71. }
  72. void RegisterCustomMemoryHook()
  73. {
  74. Allocate = AllocateHook;
  75. Free = FreeHook;
  76. AlignedAllocate = AlignedAllocateHook;
  77. AlignedFree = AlignedFreeHook;
  78. _CrtSetAllocHook(MyAllocHook);
  79. }
  80. void EnableCustomMemoryHook(bool inEnable)
  81. {
  82. sEnableCustomMemoryHook = inEnable;
  83. }
  84. bool IsCustomMemoryHookEnabled()
  85. {
  86. return sEnableCustomMemoryHook;
  87. }
  88. DisableCustomMemoryHook::DisableCustomMemoryHook()
  89. {
  90. sDisableCustomMemoryHook--;
  91. }
  92. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  93. {
  94. sDisableCustomMemoryHook++;
  95. }
  96. #else
  97. DisableCustomMemoryHook::DisableCustomMemoryHook()
  98. {
  99. }
  100. DisableCustomMemoryHook::~DisableCustomMemoryHook()
  101. {
  102. }
  103. #endif // _DEBUG && !JPH_DISABLE_CUSTOM_ALLOCATOR && !JPH_COMPILER_MINGW