diff options
-rw-r--r-- | source/blender/blenlib/BLI_vector.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh | 38 |
2 files changed, 26 insertions, 14 deletions
diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 06bafce2dd0..392b6cd9f47 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -589,7 +589,7 @@ class Vector { catch (...) { /* Destruct all values that have been moved already. */ destruct_n(begin_ + dst_index + 1, i); - end_ = begin_ + src_index; + end_ = begin_ + src_index + 1; UPDATE_VECTOR_SIZE(this); throw; } diff --git a/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh index 1e85dd4bab2..5ad7674396b 100644 --- a/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh +++ b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh @@ -1,32 +1,43 @@ #include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" #include "testing/testing.h" namespace blender::tests { -struct ExceptionThrower { +class ExceptionThrower { + private: + /* Use some random values that are unlikely to exist at the memory location already. */ static constexpr uint32_t is_alive_state = 0x21254634; static constexpr uint32_t is_destructed_state = 0xFA4BC327; - uint32_t state; + + uint32_t state_; + + /* Make use of leak detector to check if this value has been destructed. */ + void *my_memory_; + + public: bool throw_during_copy; bool throw_during_move; - ExceptionThrower() : state(is_alive_state), throw_during_copy(false), throw_during_move(false) + ExceptionThrower() + : state_(is_alive_state), + my_memory_(MEM_mallocN(1, AT)), + throw_during_copy(false), + throw_during_move(false) { } - ExceptionThrower(const ExceptionThrower &other) - : state(is_alive_state), throw_during_copy(false), throw_during_move(false) + ExceptionThrower(const ExceptionThrower &other) : ExceptionThrower() { - EXPECT_EQ(other.state, is_alive_state); + EXPECT_EQ(other.state_, is_alive_state); if (other.throw_during_copy) { throw std::runtime_error("throwing during copy, as requested"); } } - ExceptionThrower(ExceptionThrower &&other) - : state(is_alive_state), throw_during_copy(false), throw_during_move(false) + ExceptionThrower(ExceptionThrower &&other) : ExceptionThrower() { - EXPECT_EQ(other.state, is_alive_state); + EXPECT_EQ(other.state_, is_alive_state); if (other.throw_during_move) { throw std::runtime_error("throwing during move, as requested"); } @@ -34,7 +45,7 @@ struct ExceptionThrower { ExceptionThrower &operator=(const ExceptionThrower &other) { - EXPECT_EQ(other.state, is_alive_state); + EXPECT_EQ(other.state_, is_alive_state); if (throw_during_copy || other.throw_during_copy) { throw std::runtime_error("throwing during copy, as requested"); } @@ -43,7 +54,7 @@ struct ExceptionThrower { ExceptionThrower &operator=(ExceptionThrower &&other) { - EXPECT_EQ(other.state, is_alive_state); + EXPECT_EQ(other.state_, is_alive_state); if (throw_during_move || other.throw_during_move) { throw std::runtime_error("throwing during move, as requested"); } @@ -52,8 +63,9 @@ struct ExceptionThrower { ~ExceptionThrower() { - EXPECT_EQ(state, is_alive_state); - state = is_destructed_state; + EXPECT_EQ(state_, is_alive_state); + state_ = is_destructed_state; + MEM_freeN(my_memory_); } }; |