mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-28 01:03:10 -04:00
Tag operator new overloads with noexcept
According to the C++ standard, regular operator new must always return a valid pointer, and allocation failure should throw an exception. The original game did not use exceptions, and instead had its operator new return null on alloc failure. Clang and GCC seem to be enforcing the standard here, and this is causing crashes on non-Windows platforms like https://sentry.twilitrealm.dev/organizations/twilitrealm/issues/952/, where a JAISe allocation failure (custom pooled operator new overload) crashes the game when it should be handled gracefully. MSVC seems to not make use of this opportunity, meaning the code works as intended. Tagging the operators with noexcept seems to satisfy GCC, but I admit cppreference is very light on details here.
This commit is contained in:
@@ -287,28 +287,28 @@ template <typename T>
|
||||
class JASPoolAllocObject {
|
||||
public:
|
||||
#if TARGET_PC
|
||||
static void* operator new(size_t n, JKRHeapToken) {
|
||||
static void* operator new(size_t n, JKRHeapToken) IF_DUSK(noexcept) {
|
||||
return operator new(n);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* operator new(size_t n) {
|
||||
static void* operator new(size_t n) IF_DUSK(noexcept) {
|
||||
#if PLATFORM_GCN
|
||||
JASMemPool<T>& memPool_ = getMemPool_();
|
||||
#endif
|
||||
return memPool_.alloc(n);
|
||||
}
|
||||
static void* operator new(size_t n, void* ptr) {
|
||||
static void* operator new(size_t n, void* ptr) IF_DUSK(noexcept) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void operator delete(void* ptr, size_t n, JKRHeapToken) {
|
||||
static void operator delete(void* ptr, size_t n, JKRHeapToken) IF_DUSK(noexcept) {
|
||||
operator delete(ptr, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void operator delete(void* ptr, size_t n) {
|
||||
static void operator delete(void* ptr, size_t n) IF_DUSK(noexcept) {
|
||||
#if PLATFORM_GCN
|
||||
JASMemPool<T>& memPool_ = getMemPool_();
|
||||
#endif
|
||||
|
||||
@@ -237,11 +237,11 @@ enum class JKRHeapToken {
|
||||
Dummy
|
||||
};
|
||||
|
||||
inline void* operator new(size_t, JKRHeapToken, void* where) {
|
||||
inline void* operator new(size_t, JKRHeapToken, void* where) noexcept {
|
||||
return where;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t, JKRHeapToken, void* where) {
|
||||
inline void* operator new[](size_t, JKRHeapToken, void* where) noexcept {
|
||||
return where;
|
||||
}
|
||||
|
||||
@@ -264,21 +264,21 @@ inline void* operator new[](size_t, JKRHeapToken, void* where) {
|
||||
#define JKR_HEAP_TOKEN_PARAM
|
||||
#endif
|
||||
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM);
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment);
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment);
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, int alignment) IF_DUSK(noexcept);
|
||||
void* operator new(size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) IF_DUSK(noexcept);
|
||||
|
||||
// On PC, these new[] overloads are only used to catch usages of JKR_NEW with [].
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, int alignment);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, int alignment) IF_DUSK(noexcept);
|
||||
void* operator new[](size_t size JKR_HEAP_TOKEN_PARAM, JKRHeap* heap, int alignment) IF_DUSK(noexcept);
|
||||
|
||||
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM);
|
||||
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM);
|
||||
void operator delete(void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
|
||||
void operator delete[](void* ptr JKR_HEAP_TOKEN_PARAM) IF_DUSK(noexcept);
|
||||
|
||||
#if TARGET_PC
|
||||
template<typename T>
|
||||
void jkrDelete(T* ptr) {
|
||||
void jkrDelete(T* ptr) IF_DUSK(noexcept) {
|
||||
if (ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ void jkrDelete(T* ptr) {
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void jkrDelete(void* ptr) {
|
||||
inline void jkrDelete(void* ptr) IF_DUSK(noexcept) {
|
||||
if (ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -322,7 +322,7 @@ constexpr bool newArgsHasCustomAlignment() {
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) {
|
||||
T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) IF_DUSK(noexcept) {
|
||||
size_t allocSize = count * sizeof(T);
|
||||
if constexpr (!std::is_trivially_destructible<T>()) {
|
||||
static_assert(
|
||||
@@ -333,6 +333,10 @@ T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) {
|
||||
}
|
||||
|
||||
void* ptr = operator new(allocSize, JKRHeapToken::Dummy, args...);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T* dataPtr;
|
||||
if constexpr (!std::is_trivially_destructible<T>()) {
|
||||
auto length = static_cast<size_t*>(ptr);
|
||||
@@ -352,7 +356,7 @@ T* jkrNewArray(size_t count, std::in_place_type_t<T>, Args&&... args) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void jkrDeleteArray(T* pointer) {
|
||||
void jkrDeleteArray(T* pointer) IF_DUSK(noexcept) {
|
||||
if (pointer == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -372,7 +376,7 @@ void jkrDeleteArray(T* pointer) {
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void jkrDeleteArray(void* pointer) {
|
||||
inline void jkrDeleteArray(void* pointer) IF_DUSK(noexcept) {
|
||||
if (pointer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user