From e3544c9e28eded2403613d2bc5af8992c3aa734a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 20 Apr 2016 15:49:52 +0200 Subject: [PATCH] Cycles: Throw bad_alloc exception when custom allocators failed to allocate memory This mimics behavior of default allocators in STL and allows all the routines to catch out-of-memory exceptions and hopefully recover from that situation/ --- intern/cycles/util/util_guarded_allocator.h | 15 +++++++++++---- intern/cycles/util/util_stack_allocator.h | 12 +++++++++--- intern/cycles/util/util_vector.h | 6 ++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h index f6004749a13..3e63588e9b6 100644 --- a/intern/cycles/util/util_guarded_allocator.h +++ b/intern/cycles/util/util_guarded_allocator.h @@ -53,19 +53,24 @@ public: size_t size = n * sizeof(T); util_guarded_mem_alloc(size); (void)hint; -#ifdef WITH_BLENDER_GUARDEDALLOC if(n == 0) { return NULL; } + T *mem; +#ifdef WITH_BLENDER_GUARDEDALLOC /* C++ standard requires allocation functions to allocate memory suitably * aligned for any standard type. This is 16 bytes for 64 bit platform as * far as i concerned. We might over-align on 32bit here, but that should * be all safe actually. */ - return (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc"); + mem = (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc"); #else - return (T*)malloc(size); + mem = (T*)malloc(size); #endif + if(mem == NULL) { + throw std::bad_alloc(); + } + return mem; } void deallocate(T *p, size_t n) @@ -97,7 +102,9 @@ public: void construct(T *p, const T& val) { - new ((T *)p) T(val); + if(p != NULL) { + new ((T *)p) T(val); + } } void destroy(T *p) diff --git a/intern/cycles/util/util_stack_allocator.h b/intern/cycles/util/util_stack_allocator.h index 29260888eef..1acd2b18bc7 100644 --- a/intern/cycles/util/util_stack_allocator.h +++ b/intern/cycles/util/util_stack_allocator.h @@ -60,11 +60,15 @@ public: if(pointer_ + n >= SIZE) { size_t size = n * sizeof(T); util_guarded_mem_alloc(size); + T *mem; #ifdef WITH_BLENDER_GUARDEDALLOC - return (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc"); + mem = (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc"); #else - return (T*)malloc(size); + mem = (T*)malloc(size); #endif + if(mem == NULL) { + throw std::bad_alloc(); + } } T *mem = &data_[pointer_]; pointer_ += n; @@ -104,7 +108,9 @@ public: void construct(T *p, const T& val) { - new ((T *)p) T(val); + if(p != NULL) { + new ((T *)p) T(val); + } } void destroy(T *p) diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 4eb0dde8308..ad579da2d2e 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -218,10 +218,16 @@ public: protected: inline T* mem_allocate(size_t N) { + if(N == 0) { + return NULL; + } T *mem = (T*)util_aligned_malloc(sizeof(T)*N, alignment); if(mem != NULL) { util_guarded_mem_alloc(sizeof(T)*N); } + else { + throw std::bad_alloc(); + } return mem; }