You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Anton Pevtsov <An...@moscow.vdiweb.com> on 2006/05/18 17:20:20 UTC

RE: svn commit: r407397 - in /incubator/stdcxx/trunk/tests: include/rw_allocator.h src/allocator.cpp

Martin,
This code:

_RWSTD_NAMESPACE (std) {

// declare to avoid dragging in all of <memory>
// (yes, it is undefined for programs to do that)
template <class T>
struct allocator;

}   // namespace std

produces a warning on MSVC: the allocator is defined as class. 
The changing to "class allocator" eliminates the warning.
Is this change ok?


Thanks,
Anton Pevtsov



-----Original Message-----
From: sebor@apache.org [mailto:sebor@apache.org] 
Sent: Thursday, May 18, 2006 03:26
To: stdcxx-commits@incubator.apache.org
Subject: svn commit: r407397 - in /incubator/stdcxx/trunk/tests:
include/rw_allocator.h src/allocator.cpp


Author: sebor
Date: Wed May 17 16:25:58 2006
New Revision: 407397

URL: http://svn.apache.org/viewvc?rev=407397&view=rev
Log:
2006-05-17  Martin Sebor  <se...@roguewave.com>

	* rw_allocator.h (m_cpy_assign, m_cvt_assign): New constants.
	(UserAlloc::operator=): Defined.
	(rw_check_leaks): Declared and defined new helpers.
	* allocator.cpp (<driver.h>): Included for rw_assert().
	(UserAlloc ctor): Initialized n_refs_.
	(UserAlloc dtor): Invalidated member arrays.
	(_rw_check_leaks): New helper.
	(rw_check_leaks): Defined.

Modified:
    incubator/stdcxx/trunk/tests/include/rw_allocator.h
    incubator/stdcxx/trunk/tests/src/allocator.cpp

Modified: incubator/stdcxx/trunk/tests/include/rw_allocator.h
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/rw_all
ocator.h?rev=407397&r1=407396&r2=407397&view=diff
========================================================================
======
--- incubator/stdcxx/trunk/tests/include/rw_allocator.h (original)
+++ incubator/stdcxx/trunk/tests/include/rw_allocator.h Wed May 17 
+++ 16:25:58 2006
@@ -32,12 +32,26 @@
 #include <testdefs.h>
 
 
+_RWSTD_NAMESPACE (std) {
+
+// declare to avoid dragging in all of <memory>
+// (yes, it is undefined for programs to do that)
+template <class T>
+struct allocator;
+
+}   // namespace std
+
+
 struct _TEST_EXPORT SharedAlloc
 {
     // identifies each member function of a standard allocator class
     enum MemFun {
-        m_ctor, m_cvt_ctor, m_cpy_ctor,
-        m_dtor,
+        m_ctor,         // ordinary constructor
+        m_cpy_ctor,     // copy constructor
+        m_cvt_ctor,     // converting (template) constructor
+        m_cpy_assign,   // ordinary assignment operator
+        m_cvt_assign,   // converting (template) assignment operator
+        m_dtor,         // destructor
         m_allocate, m_deallocate,
         m_construct, m_destroy,
         m_address, m_max_size,
@@ -69,13 +83,14 @@
     // returns the maximum number of objects of elemsize each
     // that can be allocated from the pool managed by *this
     virtual _RWSTD_SIZE_T
-    max_size (_RWSTD_SIZE_T /* elemsize */);
+    max_size (_RWSTD_SIZE_T /* elemsize */ = 1);
 
     // records a call to the allocator member function fun and
     // throws an exception derived from std::bad_alloc if the
     // number of calls to the member function reaches the limit
     // specified by throw_at_calls_
-    virtual void funcall (MemFun /* fun */);
+    virtual void
+    funcall (MemFun /* fun */, const SharedAlloc* = 0);
 
     // gets or sets a pointer to the global allocator object
     static SharedAlloc*
@@ -84,13 +99,13 @@
     // returns a unique id of this allocator object
     int id () const { return id_; }
 
-    _RWSTD_SIZE_T max_bytes_;    // memory pool size
-    _RWSTD_SIZE_T max_blocks_;   // memory pool size
+    _RWSTD_SIZE_T max_bytes_;    // memory pool size in bytes
+    _RWSTD_SIZE_T max_blocks_;   // memory pool size in blocks
 
-    _RWSTD_SIZE_T n_bytes_;     // number of allocated bytes
-    _RWSTD_SIZE_T n_blocks_;    // number of allocated blocks
+    _RWSTD_SIZE_T n_bytes_;      // number of allocated bytes
+    _RWSTD_SIZE_T n_blocks_;     // number of allocated blocks
 
-    _RWSTD_SIZE_T n_refs_;      // number of references
+    _RWSTD_SIZE_T n_refs_;       // number of references
 
     // counter of the number of calls to each allocator member function
     _RWSTD_SIZE_T n_calls_ [n_funs];
@@ -121,7 +136,7 @@
 struct UserAlloc
 {
 // private:
-    SharedAlloc* const pal_;
+    SharedAlloc* pal_;
 
 public:
     typedef T                               value_type;
@@ -154,10 +169,21 @@
     }
 
     template <class U>
+    void operator= (const UserAlloc<U> &rhs) {
+        pal_->funcall (pal_->m_cvt_assign, rhs.pal_);
+        pal_ = rhs.pal_;
+    }
+
+    template <class U>
     struct rebind { typedef UserAlloc<U> other; };
 
 #endif   // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
 
+    void operator= (const UserAlloc &rhs) {
+        pal_->funcall (pal_->m_cpy_assign, rhs.pal_);
+        pal_ = rhs.pal_;
+    }
+
     ~UserAlloc () {
         pal_->funcall (pal_->m_dtor);
     }
@@ -204,5 +230,55 @@
     }
 };
 
+
+// when (line <= 0) establishes a new check point for memory leaks // 
+by storing the number and size of blocks of storage currently // 
+allocated by operator new and by the SharedAlloc object pointed // to 
+by palloc (when non-zero) // when (line > 0) reports the difference 
+between the the number // and size of blocks of storage allocated at 
+the last checkpoint // and the values specified by expect_blocks and 
+expect_bytes _TEST_EXPORT void
+rw_check_leaks (const SharedAlloc* /* palloc        */ = 0,
+                int                /* line          */ = 0,
+                _RWSTD_SIZE_T      /* expect_blocks */ = 0,
+                _RWSTD_SIZE_T      /* expect_bytes  */ =
_RWSTD_SIZE_MAX);
+
+
+// when (line <= 0) establishes a new check point for memory leaks // 
+by storing the number and size of blocks of storage currently // 
+allocated by operator new // when (line > 0) reports the difference 
+between the the number // and size of blocks of storage allocated at 
+the last checkpoint // and the values specified by expect_blocks and 
+expect_bytes template <class charT>
+inline void
+rw_check_leaks (const std::allocator<charT>& /* unused */,
+                int                          line          = 0,
+                _RWSTD_SIZE_T                expect_blocks = 0,
+                _RWSTD_SIZE_T                expect_bytes  =
_RWSTD_SIZE_MAX)
+{
+    // can't track memory leaks here
+    rw_check_leaks ((SharedAlloc*)0, line, expect_blocks,
expect_bytes);
+}
+
+
+// when (line <= 0) establishes a new check point for memory leaks // 
+by storing the number and size of blocks of storage currently // 
+allocated by operator new and by the user-defined allocator // 
+specified by the first argument // when (line > 0) reports the 
+difference between the the number // and size of blocks of storage 
+allocated at the last checkpoint // and the values specified by 
+expect_blocks and expect_bytes template <class charT, class Types>
+inline void
+rw_check_leaks (const UserAlloc<charT, Types> &alloc,
+                int                            line          = 0,
+                _RWSTD_SIZE_T                  expect_blocks = 0,
+                _RWSTD_SIZE_T                  expect_bytes  =
_RWSTD_SIZE_MAX)
+{
+    // track memory leaks via SharedAlloc
+    rw_check_leaks (alloc.pal_, line, expect_blocks, expect_bytes);
+}
 
 #endif   // RW_ALLOCATOR_INCLUDED

Modified: incubator/stdcxx/trunk/tests/src/allocator.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/allocator.
cpp?rev=407397&r1=407396&r2=407397&view=diff
========================================================================
======
--- incubator/stdcxx/trunk/tests/src/allocator.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/allocator.cpp Wed May 17 16:25:58 
+++ 2006
@@ -30,6 +30,7 @@
 
 #include <rw_allocator.h>
 #include <rw_new.h>         // for operator_new()
+#include <driver.h>         // for rw_assert()
 #include <new>              // for bad_alloc, placement new
 #include <stdarg.h>         // for va_arg(), va_list
 #include <string.h>         // for memset()
@@ -39,15 +40,17 @@
 static const char* const
 _rw_funnames[] = {
     "UserAlloc::UserAlloc ()",
-    "UserAlloc::UserAlloc (const UserAlloc<U>&)",
     "UserAlloc::UserAlloc (const UserAlloc&)",
+    "UserAlloc::UserAlloc (const UserAlloc<U>&)",
     "UserAlloc::~UserAlloc ()",
+    "UserAlloc::operator= (const UserAlloc&)",
+    "UserAlloc::operator=<U>(const UserAlloc<U>&)",
     "UserAlloc::allocate (size_type, void*)",
     "UserAlloc::deallocate (pointer, size_type)",
     "UserAlloc::construct (pointer, const_reference)",
     "UserAlloc::destroy (pointer)",
-    "UserAlloc::address (reference)",
-    "UserAlloc::max_size ()"
+    "UserAlloc::address (reference) const",
+    "UserAlloc::max_size () const"
 };
 
 static int _rw_id_gen;   // generates unique ids
@@ -88,7 +91,7 @@
 SharedAlloc::
 SharedAlloc (size_t nbytes /* = MAX_SIZE */, size_t nblocks /* =
MAX_SIZE */)
     : max_bytes_ (nbytes), max_blocks_ (nblocks),
-      n_bytes_ (0), n_blocks_ (0), id_ (0)
+      n_bytes_ (0), n_blocks_ (0), n_refs_ (0), id_ (0)
 {
     memset (n_calls_, 0, sizeof n_calls_);
     memset (throw_at_calls_, -1, sizeof throw_at_calls_);
@@ -98,7 +101,25 @@
 /* virtual */ SharedAlloc::
 ~SharedAlloc ()
 {
-    // no-op
+    static size_t deadbeef = 0;
+    if (0 == deadbeef) {
+        deadbeef = size_t (0xdeadbeefU);
+        if (deadbeef < deadbeef << 1) {
+            // assume 64-bit size_t
+            deadbeef <<= 31;
+            deadbeef <<=  1;
+            deadbeef  |= size_t (0xdeadbeefU);
+        }
+    }
+
+    // invalidate
+    size_t n = sizeof n_calls_ / sizeof *n_calls_;
+    for (size_t i = 0; i != n; ++i)
+        n_calls_ [i] = deadbeef;
+
+    n = sizeof throw_at_calls_ / sizeof *throw_at_calls_;
+    for (size_t i = 0; i != n; ++i)
+        throw_at_calls_ [i] = deadbeef;
 }
 
 
@@ -133,7 +154,7 @@
 
 
 /* virtual */ size_t SharedAlloc::
-max_size (size_t size)
+max_size (size_t size /* = 1 */)
 {
     funcall (m_max_size);
 
@@ -142,7 +163,7 @@
 
 
 /* virtual */ void SharedAlloc::
-funcall (MemFun mf)
+funcall (MemFun mf, const SharedAlloc *other /* = 0 */)
 {
     if (m_ctor == mf) {
         // ordinary (not a copy or converting) ctor
@@ -162,6 +183,27 @@
         // increment the number of references to this allocator
         ++n_refs_;
     }
+    else if (m_cpy_assign == mf || m_cvt_assign == mf) {
+        // assignment operator
+        RW_ASSERT (0 <= id_ && id_ <= _rw_id_gen);
+        RW_ASSERT (0 < n_refs_);
+
+        RW_ASSERT (0 != other);
+
+        if (this != other) {
+            // decrement the number of references and invalidate
+            // id if no object refers to *this
+            if (0 == --n_refs_)
+                id_ = -1;
+
+            SharedAlloc* const po = _RWSTD_CONST_CAST (SharedAlloc*, 
+ other);
+
+            if (other->id_ <= 0)
+                po->id_ = ++_rw_id_gen;
+
+            ++po->n_refs_;
+        }
+    }
     else if (m_dtor == mf) {
         // dtor
         RW_ASSERT (0 <= id_ && id_ <= _rw_id_gen);
@@ -210,4 +252,76 @@
     RW_ASSERT (0 != pinst);
 
     return pinst;
+}
+
+/**********************************************************************
+****/
+
+static void
+_rw_check_leaks (int line, size_t expect_blocks, size_t expect_bytes) {
+    if (0 < line) {
+        // determine and report memory leaks since last checkpoint
+
+        /* const */ size_t nbytes;
+        const       size_t nblocks = rwt_check_leaks (&nbytes, 0);
+
+        if (_RWSTD_SIZE_MAX == expect_blocks)
+            expect_blocks = nblocks;
+
+        if (_RWSTD_SIZE_MAX == expect_bytes)
+            expect_bytes = nbytes;
+
+        rw_assert (nblocks == expect_blocks && nbytes == expect_bytes,
+                   0, line,
+                   "line %d. %{$FUNCALL} operator new allocated "
+                   "%zu bytes in %zu blocks, expected %zu bytes "
+                   "in %zu blocks",
+                   __LINE__, nbytes, nblocks,
+                   expect_bytes, expect_blocks);
+    }
+    else {
+        // establish a checkpoint for memory leaks
+        rwt_check_leaks (0, 0);
+    }
+}
+
+
+_TEST_EXPORT void
+rw_check_leaks (const SharedAlloc *palloc        /* =  0 */,
+                int                line          /* =  0 */, 
+                size_t             expect_blocks /* =  0 */,
+                size_t             expect_bytes  /* = -1 */)
+{
+    _rw_check_leaks (line, expect_blocks, expect_bytes);
+
+    if (0 == palloc)
+        return;
+
+    static size_t nbytes;
+    static size_t nblocks;
+
+    if (0 < line) {
+        // determine and report memory leaks since last checkpoint
+        const size_t leaked_bytes  = palloc->n_bytes_ - nbytes;
+        const size_t leaked_blocks = palloc->n_blocks_ - nblocks;
+
+        if (_RWSTD_SIZE_MAX == expect_blocks)   // don't care
+            expect_blocks = leaked_blocks;
+
+        if (_RWSTD_SIZE_MAX == expect_bytes)   // don't care
+            expect_bytes = nbytes;
+
+        rw_assert (   leaked_blocks == expect_blocks
+                   && leaked_bytes == expect_bytes, 0, line,
+                   "line %d. %{$FUNCALL} UserAlloc allocated "
+                   "%zu bytes in %zu blocks, expected %zu bytes "
+                   "in %zu blocks",
+                   __LINE__, leaked_bytes, leaked_blocks,
+                   expect_bytes, expect_blocks);
+    }
+    else {
+        // establish a checkpoint for memory leaks
+        nbytes  = palloc->n_bytes_;
+        nblocks = palloc->n_blocks_;
+    }
 }



Re: svn commit: r407397 - in /incubator/stdcxx/trunk/tests: include/rw_allocator.h src/allocator.cpp

Posted by Martin Sebor <se...@roguewave.com>.
Anton Pevtsov wrote:
> Martin,
> This code:
> 
> _RWSTD_NAMESPACE (std) {
> 
> // declare to avoid dragging in all of <memory>
> // (yes, it is undefined for programs to do that)
> template <class T>
> struct allocator;
> 
> }   // namespace std
> 
> produces a warning on MSVC: the allocator is defined as class. 
> The changing to "class allocator" eliminates the warning.
> Is this change ok?

The warning is bogus -- from a language standpoint there is no
difference between class or struct in the declaration of a class,
only in the definition of it. But I will change the class-key
from struct to class just to silence the warning. Thanks for
pointing it out!

Martin