From 4d5b9a80cf14a9993b2c287091a4a096cdcc6f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 23 Sep 2014 17:29:26 +0200 Subject: [PATCH] Added life cout and double destruction assertions to test integer-like classes. Changelog updated with double destruction bugs fix. --- doc/container.qbk | 1 + test/movable_int.hpp | 125 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 21 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index be85294..9704d89 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1060,6 +1060,7 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_57_00 Boost 1.57 Release] * Added support for `initializer_list`. Contributed by Robert Matusewicz. +* Fixed double destruction bugs in vector and backward expansion capable allocators. * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/10263 Trac #10263 (['"AIX 6.1 bug with sched_yield() function out of scope"])]. * [@https://github.com/boostorg/container/pull/16 GitHub #16: ['Fix iterators of incomplete type containers]]. Thanks to Mikael Persson. diff --git a/test/movable_int.hpp b/test/movable_int.hpp index ad01d63..38678d7 100644 --- a/test/movable_int.hpp +++ b/test/movable_int.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include namespace boost { namespace container { @@ -35,26 +37,38 @@ class movable_int BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int) public: + + static unsigned int count; + movable_int() : m_int(0) - {} + { ++count; } explicit movable_int(int a) : m_int(a) - {} + { + //Disallow INT_MIN + BOOST_ASSERT(this->m_int != INT_MIN); + ++count; + } movable_int(BOOST_RV_REF(movable_int) mmi) : m_int(mmi.m_int) - { mmi.m_int = 0; } + { mmi.m_int = 0; ++count; } movable_int & operator= (BOOST_RV_REF(movable_int) mmi) - { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } + { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } movable_int & operator= (int i) - { this->m_int = i; return *this; } + { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; } ~movable_int() - { this->m_int = 0; } + { + //Double destructor called + BOOST_ASSERT(this->m_int != INT_MIN); + this->m_int = INT_MIN; + --count; + } friend bool operator ==(const movable_int &l, const movable_int &r) { return l.m_int == r.m_int; } @@ -87,6 +101,8 @@ class movable_int int m_int; }; +unsigned int movable_int::count = 0; + inline movable_int produce_movable_int() { return movable_int(); } @@ -110,24 +126,36 @@ class movable_and_copyable_int BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int) public: + + static unsigned int count; + movable_and_copyable_int() : m_int(0) - {} + { ++count; } explicit movable_and_copyable_int(int a) : m_int(a) - {} + { + //Disallow INT_MIN + BOOST_ASSERT(this->m_int != INT_MIN); + ++count; + } movable_and_copyable_int(const movable_and_copyable_int& mmi) : m_int(mmi.m_int) - {} + { ++count; } movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi) : m_int(mmi.m_int) - { mmi.m_int = 0; } + { mmi.m_int = 0; ++count; } ~movable_and_copyable_int() - { this->m_int = 0; } + { + //Double destructor called + BOOST_ASSERT(this->m_int != INT_MIN); + this->m_int = INT_MIN; + --count; + } movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) { this->m_int = mi.m_int; return *this; } @@ -136,7 +164,7 @@ class movable_and_copyable_int { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } movable_and_copyable_int & operator= (int i) - { this->m_int = i; return *this; } + { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; } friend bool operator ==(const movable_and_copyable_int &l, const movable_and_copyable_int &r) { return l.m_int == r.m_int; } @@ -169,6 +197,8 @@ class movable_and_copyable_int int m_int; }; +unsigned int movable_and_copyable_int::count = 0; + inline movable_and_copyable_int produce_movable_and_copyable_int() { return movable_and_copyable_int(); } @@ -190,26 +220,38 @@ struct is_copyable class copyable_int { public: + + static unsigned int count; + copyable_int() : m_int(0) - {} + { ++count; } explicit copyable_int(int a) : m_int(a) - {} + { + //Disallow INT_MIN + BOOST_ASSERT(this->m_int != INT_MIN); + ++count; + } copyable_int(const copyable_int& mmi) : m_int(mmi.m_int) - {} + { ++count; } copyable_int & operator= (int i) - { this->m_int = i; return *this; } + { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; } copyable_int & operator= (const copyable_int &ci) - { this->m_int = ci.m_int; return *this; } + { this->m_int = ci.m_int; BOOST_ASSERT(this->m_int != INT_MIN); return *this; } ~copyable_int() - { this->m_int = 0; } + { + //Double destructor called + BOOST_ASSERT(this->m_int != INT_MIN); + this->m_int = INT_MIN; + --count; + } friend bool operator ==(const copyable_int &l, const copyable_int &r) { return l.m_int == r.m_int; } @@ -242,6 +284,8 @@ class copyable_int int m_int; }; +unsigned int copyable_int::count = 0; + inline copyable_int produce_copyable_int() { return copyable_int(); } @@ -266,16 +310,19 @@ class non_copymovable_int non_copymovable_int & operator= (const non_copymovable_int &mi); public: + + static unsigned int count; + non_copymovable_int() : m_int(0) - {} + { ++count; } explicit non_copymovable_int(int a) : m_int(a) - {} + { ++count; } ~non_copymovable_int() - { m_int = 0; } + { m_int = 0; --count; } bool operator ==(const non_copymovable_int &mi) const { return this->m_int == mi.m_int; } @@ -308,6 +355,42 @@ class non_copymovable_int int m_int; }; +unsigned int non_copymovable_int::count = 0; + +template +struct life_count +{ + static unsigned check(unsigned) { return true; } +}; + +template<> +struct life_count< movable_int > +{ + static unsigned check(unsigned c) + { return c == movable_int::count; } +}; + +template<> +struct life_count< copyable_int > +{ + static unsigned check(unsigned c) + { return c == copyable_int::count; } +}; + +template<> +struct life_count< movable_and_copyable_int > +{ + static unsigned check(unsigned c) + { return c == movable_and_copyable_int::count; } +}; + +template<> +struct life_count< non_copymovable_int > +{ + static unsigned check(unsigned c) + { return c == non_copymovable_int::count; } +}; + } //namespace test { } //namespace container {