瀏覽代碼

32-bit MinGW g++ doesn't call the correct overload for the new operator when a type is 16 bytes aligned. (#1614)

It uses the non-aligned version, which on 32 bit platforms usually returns an 8 byte aligned block. We therefore default to 16 byte aligned allocations when the regular new operator is used.

See: https://github.com/godotengine/godot/issues/105455#issuecomment-2825380494
Jorrit Rouwe 3 月之前
父節點
當前提交
fd37495ad7
共有 2 個文件被更改,包括 17 次插入4 次删除
  1. 1 0
      Docs/ReleaseNotes.md
  2. 16 4
      Jolt/Core/Memory.h

+ 1 - 0
Docs/ReleaseNotes.md

@@ -11,6 +11,7 @@ For breaking API changes see [this document](https://github.com/jrouwe/JoltPhysi
 
 
 ### Bug Fixes
 ### Bug Fixes
 
 
+* 32-bit MinGW g++ doesn't call the correct overload for the new operator when a type is 16 bytes aligned. This could cause unaligned read access violations.
 * Fixed compiling in double precision and fixed issues with floating point contraction that caused unit test failures on LoongArch architecture.
 * Fixed compiling in double precision and fixed issues with floating point contraction that caused unit test failures on LoongArch architecture.
 * Added an epsilon to the `CastRay` / `CastShape` early out condition to avoid dividing by a very small number and overflowing to INF. This can cause a float overflow exception.
 * Added an epsilon to the `CastRay` / `CastShape` early out condition to avoid dividing by a very small number and overflowing to INF. This can cause a float overflow exception.
 * Fixed Samples requiring Vulkan extension `VK_EXT_device_address_binding_report` without checking if it is available.
 * Fixed Samples requiring Vulkan extension `VK_EXT_device_address_binding_report` without checking if it is available.

+ 16 - 4
Jolt/Core/Memory.h

@@ -27,12 +27,24 @@ JPH_EXPORT extern AlignedFreeFunction AlignedFree;
 /// Register platform default allocation / free functions
 /// Register platform default allocation / free functions
 JPH_EXPORT void RegisterDefaultAllocator();
 JPH_EXPORT void RegisterDefaultAllocator();
 
 
+// 32-bit MinGW g++ doesn't call the correct overload for the new operator when a type is 16 bytes aligned.
+// It uses the non-aligned version, which on 32 bit platforms usually returns an 8 byte aligned block.
+// We therefore default to 16 byte aligned allocations when the regular new operator is used.
+// See: https://github.com/godotengine/godot/issues/105455#issuecomment-2824311547
+#if defined(JPH_COMPILER_MINGW) && JPH_CPU_ADDRESS_BITS == 32
+	#define JPH_INTERNAL_DEFAULT_ALLOCATE(size) JPH::AlignedAllocate(size, 16)
+	#define JPH_INTERNAL_DEFAULT_FREE(pointer) JPH::AlignedFree(pointer)
+#else
+	#define JPH_INTERNAL_DEFAULT_ALLOCATE(size) JPH::Allocate(size)
+	#define JPH_INTERNAL_DEFAULT_FREE(pointer) JPH::Free(pointer)
+#endif
+
 /// Macro to override the new and delete functions
 /// Macro to override the new and delete functions
 #define JPH_OVERRIDE_NEW_DELETE \
 #define JPH_OVERRIDE_NEW_DELETE \
-	JPH_INLINE void *operator new (size_t inCount)												{ return JPH::Allocate(inCount); } \
-	JPH_INLINE void operator delete (void *inPointer) noexcept									{ JPH::Free(inPointer); } \
-	JPH_INLINE void *operator new[] (size_t inCount)											{ return JPH::Allocate(inCount); } \
-	JPH_INLINE void operator delete[] (void *inPointer) noexcept								{ JPH::Free(inPointer); } \
+	JPH_INLINE void *operator new (size_t inCount)												{ return JPH_INTERNAL_DEFAULT_ALLOCATE(inCount); } \
+	JPH_INLINE void operator delete (void *inPointer) noexcept									{ JPH_INTERNAL_DEFAULT_FREE(inPointer); } \
+	JPH_INLINE void *operator new[] (size_t inCount)											{ return JPH_INTERNAL_DEFAULT_ALLOCATE(inCount); } \
+	JPH_INLINE void operator delete[] (void *inPointer) noexcept								{ JPH_INTERNAL_DEFAULT_FREE(inPointer); } \
 	JPH_INLINE void *operator new (size_t inCount, std::align_val_t inAlignment)				{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \
 	JPH_INLINE void *operator new (size_t inCount, std::align_val_t inAlignment)				{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \
 	JPH_INLINE void operator delete (void *inPointer, [[maybe_unused]] std::align_val_t inAlignment) noexcept	{ JPH::AlignedFree(inPointer); } \
 	JPH_INLINE void operator delete (void *inPointer, [[maybe_unused]] std::align_val_t inAlignment) noexcept	{ JPH::AlignedFree(inPointer); } \
 	JPH_INLINE void *operator new[] (size_t inCount, std::align_val_t inAlignment)				{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \
 	JPH_INLINE void *operator new[] (size_t inCount, std::align_val_t inAlignment)				{ return JPH::AlignedAllocate(inCount, static_cast<size_t>(inAlignment)); } \