Re: Is it the BUG of VC 7.1

From: tom_usenet (tom_usenet_at_hotmail.com)
Date: 12/19/03


Date: Fri, 19 Dec 2003 22:30:20 +0000

On Fri, 19 Dec 2003 09:27:23 +0800, "Darkay Li"
<darkay_li@hotmail.com> wrote:

>I have try to create an allocator like follow:
> // the type of allocator must be some kind of pointer
> template <class Type>
> class PointerAllocator : public std::allocator<Type>
> {
> public:
> typedef std::allocator<Type> BaseClass;
>
> public:
> void destroy(pointer ptr)
> {
> delete (*ptr); // "Type" must be a pointer of object
> BaseClass::destroy(ptr);
> }
> };
>
>My allocator derive from the std::allocator, and just rewrite the destroy
>method, to delete the object which the pointer pointer at.

What makes you think that your destroy member will be called? If you
allocator is rebound, the rebound type will be a std::allocator, not
your allocator, and hence your destroy won't be used.

In fact, your allocator doesn't conform to allocator requirements:
Alloc::rebind<U>::other::rebind<T>::other has to be the same as Alloc
(for T). This isn't the case with yours, hence the problems.

>and then I create three containers:
> template <class Type>
> class PointerList : public std::list<Type, PointerAllocator<Type> >
> {
> };
>
> template <class Type>
> class PointerDeque : public std::deque<Type, PointerAllocator<Type> >
> {
> };
>
> template<class Key, class Type, class Traits = less<Key> >
> class PointerMap : public std::map<Key, Type, Traits,
>PointerAllocator<Type> >
> {
> };
>These container can store pointer of the object and free the object it self.

Did you actually test this? You may find that your destroy member is
never called.

>
>at last I write my test code:
>int main(int argc, char* argv[])
>{
> PointerDeque<int *> pd;
> pd.push_back(new int(10));
> int *p = pd.front();
> cout << *p << endl;
>
> PointerList<int *> pl;
> pl.push_back(new int (10));
> cout << **pl.begin() << endl;
>
> PointerMap<int , int *> pm;
> pm[1] = new int(10);
> cout << *pm[1] << endl;
>
> return 0;
>}
>everything OK when I using VC6 and SGI's STL(both VC6 and VC7.1),

When you say ok, was your destroy function actually called?

 but when I
>compile the test code with VC7.1(P.J STL) I got error (error message show in
>the end). I check the error and find it's the problem of deque's iterator.
>In VC7.1 the iterator of deque definition is:
> class iterator
> : public const_iterator
> { // iterator for mutable deque
> public:
> //......
> iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
> : const_iterator(_Off, _Pdeque)
> { // construct with offset _Off in *_Pdeque
> }
> }
>the constructor prototype of iterator is :
>iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
>and I find it's different from const_iterator's constructor prototype:
>const_iterator(size_type _Off, const _Myt *_Pdeque)
>
>Why not use the same definiation of const_iterator?

Well, according to the allocator requirements, _Myt and deque<Ty,
_Alloc> are the same type, so the implementation is allowed to use
them interchangeably.

>when I modify the constructor of iterator as the same with const_iterator.
>the all my test code compile pass(and run OK).
>Is it the BUG of VC7.1 ?

No. Your approach isn't going to work. For a start you will have
double deletion problems. Instead I would recommend either writing a
container adapter for pointer holding containers that deletes pointers
when necessary, or use a container<shared_ptr<T> >. e.g.

template <class Cont>
class pointer_container
{
protected:
  Cont c;
public:
  typedef typename Cont::iterator iterator;
  //...
  typedef typename Cont::value_type value_type;

  

  void pop_back()
  {
     delete c.back();
     c.pop_back();
  }

  //etc.
};

Remember that mutating algorithms (like remove_if) will still cause
problems.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html



Relevant Pages

  • Re: Is There Any Reason to Even Use VC++ Anymore?
    ... pointer if you own it and a reference if owned externally is broken (not ... especially if this number is only limited by available memory or dictated ... It doesn't know if A still exists, so it can't destroy X. ... Note that A is the allocator of X, but can't be the destroyer if A goes away ...
    (microsoft.public.dotnet.languages.vc)
  • Re: clear() on vectors
    ... it is a pointer to iterator ... >But was it the iterator you wanted to destroy? ... Normally you want to destroy the item ... one to mark the beginning, ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Fragmented memory compaction ???
    ... If you've never written a garbage-collecting allocator that also ... Smart pointers are a good bet, because they agressively free storage when the reference ... They won't do compaction, but they will handle the case of not worrying ... pointer" class where every access to the object is dereferenced via an indirect pointer ...
    (microsoft.public.vc.mfc)
  • Re: MDI as SDI
    ... > I decided to "fake" SDI by handling New, Open, Close, etc. such that only ... > // there are cases where destroying the documents may destroy the ... > // main window of the application. ... because the pointer is not NULL ...
    (microsoft.public.vc.mfc)
  • Re: Fragmented memory compaction ???
    ... pointer" class where every access to the object is dereferenced via an indirect pointer ... Compaction and garbage collection are not at all the same, ... a contiguous block of allocated storage, and a contiguous block of free ... even a simple, single-threaded storage allocator (I've done it, and written a book chapter ...
    (microsoft.public.vc.mfc)

Loading