BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

smart pointer class
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++)
View previous topic :: View next topic  
Author Message
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 6:15 am    Post subject: smart pointer class Reply with quote



I've written a smart pointer class because I didn't like being dependant on
the boost library, but for some reason there must be a bug in it that I
can't see because I keep on gettting problems with it.

It is a shared pointer class, so that makes it more complicated, but I
can't see my bug.

Can anyone point out to me the problem ?

template <class T> class JFSmartPtrData
{
public:
T *Ptr;
int RefCount;

JFSmartPtrData() : Ptr( NULL ), RefCount( 0 ) { }
~JFSmartPtrData() { }
};

template <class T> class JFSmartPtr
{
private:
bool OwnsData;

void ReleaseDataPtr()
{
if( Data->Ptr && --Data->RefCount < 1 )
{
delete Data->Ptr;
Data->Ptr = NULL;
}
}

void ReleaseData()
{
if( OwnsData )
{
delete Data;
Data = NULL;
}
}

public:
JFSmartPtr( T *PPtr = NULL )
: Data( new JFSmartPtrData<T>() ), OwnsData( true )
{
Data->Ptr = PPtr;
Data->RefCount = 1;
}

JFSmartPtr( JFSmartPtr const &PInstance )
: OwnsData( false )
{
Data = PInstance.Data;
++Data->RefCount;
}

~JFSmartPtr()
{
ReleaseDataPtr();
ReleaseData();
}

void Reset( T *PPtr = NULL )
{
ReleaseDataPtr();

Data->Ptr = PPtr;
Data->RefCount = 1;
}

void reset( T *PPtr = NULL )
{
Reset( PPtr );
}

T* GetPtr() const
{
return Data->Ptr;
}

T* get() const
{
return GetPtr();
}

JFSmartPtr& operator =( JFSmartPtr const &PInstance )
{
ReleaseDataPtr();
ReleaseData();

Data = PInstance.Data;
++Data->RefCount;

return *this;
}

T* operator-> () const
{
return GetPtr();
}

JFSmartPtrData<T> *Data;
};


Jonathan


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 06, 2005 6:35 am    Post subject: Re: smart pointer class Reply with quote




"Jonathan Benedicto" <incorrect (AT) no (DOT) server> wrote


Quote:
for some reason there must be a bug in it that I can't see
because I keep on gettting problems with it.

It would help if you would explain what kinds of problems you are actually
having with it.

Quote:
JFSmartPtr& operator =( JFSmartPtr const &PInstance )

This operator looks suspicious to me. You are not doing anything with the
OwnsData member at all. If you instantiate two default-created instances
and then assign one to the other, you now have two instances that own the
same data.

Are you intending for the '=' operator to just pass the T* pointer around,
or to actually pass ownership of the data around? If the latter case, then
you are not managing the data properly.


Gambit



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 7:36 am    Post subject: Re: smart pointer class Reply with quote



Remy Lebeau (TeamB) wrote:
Quote:
It would help if you would explain what kinds of problems you are
actually having with it.

I'm sorry about not giving enough detail. Basically I just get AV's in
places in the smart pointers code as it tries to access a freed member
function.

Quote:
JFSmartPtr& operator =( JFSmartPtr const &PInstance )

This operator looks suspicious to me. You are not doing anything
with the OwnsData member at all. If you instantiate two
default-created instances and then assign one to the other, you now
have two instances that own the same data.

Are you intending for the '=' operator to just pass the T* pointer
around, or to actually pass ownership of the data around? If the
latter case, then you are not managing the data properly.

It is the latter case. Thank you for seeing this, I think that this might
have been the problem.

Jonathan



Back to top
Alisdair Meredith [TeamB]
Guest





PostPosted: Tue Dec 06, 2005 10:11 am    Post subject: Re: smart pointer class Reply with quote

Jonathan Benedicto wrote:

Quote:
I've written a smart pointer class because I didn't like being
dependant on the boost library, but for some reason there must be a
bug in it that I can't see because I keep on gettting problems with
it.

Experience has shown smart pointer libraries to be extremely subtle
beasts to get exactly right. I hope you have a large library of tests!


Why do you want to avoid the boost library in this case? shared_ptr is
a well tested, robust librry that has been accepted as parts of std
library TR1. I would think very carefully about what advantages my own
library adds before putting it into production use - and so far have
not found a good reason to write my own.

Note that I think writing such a smart pointer IS a very valuable
exercise, you can learn a lot from doing this, I would just think very
carefully before putting it into production use over shared_ptr.
Please don't take the following comments as a discouragement - more a
quick distilling of what I learned looking at boost implementation over
the years:

i/ You have no thread safety here at all (boost now have a very
efficient 'lock free' implementation)

ii/ You cannot use incomplete types, so not appropriate for pImpl idiom

iii/ Owned property and reference count in the same class is a very
confusing interface

iv/ How will you break cycles, where 2 shared objects have references
to each other

v/ What about smart-cast operators, to dynamic_cast your pointer to a
smart-ptr-to-derived-type

vi/ No operator< support, so cannt be used as key to a map

vii/ cannot cope with arrays (will not call delete[] when appropriate)

viii/ cannot handle objects allocated by a different memory manager, eg
in a different DLL

ix/ cannot copy constuct or assign with smart-ptr-to-derived objects.


And that is without looking at implementation for subtle bugs, such as
smart-ptrs used in composites re-assigned to their sub-components.
[May be supported, haven't checked]


Which unfortunately means I haven't had time to track your actual
support request either. Sorry Will try to take a look at this over lunch.

--

AlisdairM(TeamB)

Back to top
Alan Bellingham
Guest





PostPosted: Tue Dec 06, 2005 10:15 am    Post subject: Re: smart pointer class Reply with quote

"Jonathan Benedicto" <incorrect (AT) no (DOT) server> wrote:

Quote:
I've written a smart pointer class because I didn't like being dependant on
the boost library, but for some reason there must be a bug in it that I
can't see because I keep on gettting problems with it.

This is often the problem with attempting to write your own version of
something in the C++ Standard*. That they didn't feel that the original
smart pointers were ready for the first version of the standard (so we
only got auto_ptr<>, which has its uses, but not as a generic smart
pointer) should be an indication that it wasn't as easy as it appeared.

Did you look at the source for the boost smart pointer classes?

*As of TR1

Alan Bellingham
--
ACCU Conference 2006 - 19-22 April, Randolph Hotel, Oxford, UK

Back to top
Alan Bellingham
Guest





PostPosted: Tue Dec 06, 2005 10:26 am    Post subject: Re: smart pointer class Reply with quote

Alan Bellingham <alanb (AT) episys (DOT) com> wrote:

Quote:
... should be an indication that it wasn't as easy as it appeared.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html#Implementation-difficulty
for some comment about this, including "The number of subtle ways in
which reference-counting smart pointers can fail is remarkable."

Alan Bellingham
--
ACCU Conference 2006 - 19-22 April, Randolph Hotel, Oxford, UK

Back to top
tinyabs
Guest





PostPosted: Tue Dec 06, 2005 12:12 pm    Post subject: Re: smart pointer class Reply with quote

Personally I have a smart pointer class but it's not widely use by me.
Pointers and auto_ptr is still the main practice.

I understand some of us, including me, is looking or had looked at an ideal
environment where memory management are automatic. In that case, take a look
at D ([url]www.digitalmars.com)[/url]. It was announced in 1999 and currently has a
compiler (DMD) and a few lousy IDEs. The inventor is Walter Bright, a smart
guy who written other C/C++ compiler too. C++ programmers will find it easy
to pick up and it has many glorious language feature. However, it is still
in development stage.

Anyway, this is a good way to learn const correctness and operators in your
class design.


Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:16 pm    Post subject: Re: smart pointer class Reply with quote

Alisdair Meredith [TeamB] wrote:
Quote:
Experience has shown smart pointer libraries to be extremely subtle
beasts to get exactly right. I hope you have a large library of
tests!

Well, I don't have too many. Just my mtbcc32 and a few other test apps that
I could throw together.

Quote:
Why do you want to avoid the boost library in this case? shared_ptr
is a well tested, robust librry that has been accepted as parts of std
library TR1. I would think very carefully about what advantages my
own library adds before putting it into production use - and so far
have not found a good reason to write my own.

Boost is kinda big, and whenever I want to give code to someone, I don't
like to have to tell them to get boost.

Quote:
Note that I think writing such a smart pointer IS a very valuable
exercise, you can learn a lot from doing this, I would just think very
carefully before putting it into production use over shared_ptr.
Please don't take the following comments as a discouragement - more a
quick distilling of what I learned looking at boost implementation
over the years:

i/ You have no thread safety here at all (boost now have a very
efficient 'lock free' implementation)

I figured that the user of the class could take care of this, not knowing
that shared_ptr actually was thread-safe.

Quote:
ii/ You cannot use incomplete types, so not appropriate for pImpl
idiom

Hmm, I'll have to check that out, thank you.

Quote:
iii/ Owned property and reference count in the same class is a very
confusing interface

I know, but I couldn't figure out a better way to handle the situation when
2 JMSmartPtrs own the same pointer and they are deleted. I think that I
encountered problems with my ref count.

Quote:
iv/ How will you break cycles, where 2 shared objects have references
to each other

Please could you explain this further.

Quote:
v/ What about smart-cast operators, to dynamic_cast your pointer to a
smart-ptr-to-derived-type

I hadn't thought of this, will have to add it.

Quote:
vi/ No operator< support, so cannt be used as key to a map

I'll have to see boosts code to figure out what this is for.

Quote:
vii/ cannot cope with arrays (will not call delete[] when appropriate)

For this, I wrote a separate JFSmartArray, that is basically the same
except for the delete[]

Quote:
viii/ cannot handle objects allocated by a different memory manager,
eg in a different DLL

I'll have to figure this out.

Quote:
ix/ cannot copy constuct or assign with smart-ptr-to-derived objects.

I thought that I had a copy constructor. I'll have to go and look that up.

Quote:
Which unfortunately means I haven't had time to track your actual
support request either. Sorry Will try to take a look at this over lunch.

Thank you very much, I really appreciate this.

Jonathan



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:17 pm    Post subject: Re: smart pointer class Reply with quote

Alan Bellingham wrote:
Quote:
This is often the problem with attempting to write your own version of
something in the C++ Standard*. That they didn't feel that the
original smart pointers were ready for the first version of the
standard (so we only got auto_ptr<>, which has its uses, but not as a
generic smart pointer) should be an indication that it wasn't as easy
as it appeared.

*As of TR1

Did you look at the source for the boost smart pointer classes?

No I didn't, But I will.

Jonathan



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:17 pm    Post subject: Re: smart pointer class Reply with quote

Alan Bellingham wrote:
Quote:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html#Implementation-difficulty
for some comment about this, including "The number of subtle ways in
which reference-counting smart pointers can fail is remarkable."

As I've noticed. :)

Jonathan



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:19 pm    Post subject: Re: smart pointer class Reply with quote

Tom Widmer wrote:
Quote:
Why?

Because Boost is so big, and I don't like having to tell people to whom I
give code to, to get boost.

Quote:
That data member is very suspicious. I can't think of a reason to have
such a member in a reference counted smart pointer. Get rid of it, and
you'll find things start to get better. Basically, you should delete
your data class directly after deleting the Ptr member. In fact, you
should probably just have:

~JFSmartPtrData() {delete Ptr;}

to enforce that - just delete the Data member to delete the held
object. Anyway, it's true that writing a good, reliable smart pointer
class is very difficult.

I'll have to go through that code again, and see if I can re-work it
better.

Jonathan



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:20 pm    Post subject: Re: smart pointer class Reply with quote

tinyabs wrote:
Quote:
I understand some of us, including me, is looking or had looked at an
ideal environment where memory management are automatic. In that
case, take a look at D ([url]www.digitalmars.com)[/url]. It was announced in
1999 and currently has a compiler (DMD) and a few lousy IDEs. The
inventor is Walter Bright, a smart guy who written other C/C++
compiler too. C++ programmers will find it easy to pick up and it has
many glorious language feature. However, it is still in development
stage.

I'm afraid that I want to stick to C++.

Quote:
Anyway, this is a good way to learn const correctness and operators
in your class design.

Good.

Jonathan



Back to top
Jonathan Benedicto
Guest





PostPosted: Tue Dec 06, 2005 3:47 pm    Post subject: Re: smart pointer class Reply with quote

New code:

template <class T> class JFSmartPtrData
{
public:
T *Ptr;
int RefCount;

JFSmartPtrData() : Ptr( NULL ), RefCount( 0 ) { }
~JFSmartPtrData()
{
if( Ptr )
delete Ptr;
}
};
//---------------------------------------------------------------------------
template <class T> class JFSmartPtr
{
private:
JFSmartPtrData<T> *Data;

void ReleaseData()
{
if( --Data->RefCount < 1 )
{
delete Data;
Data = NULL;
}
}

public:
JFSmartPtr( T *PPtr = NULL )
: Data( new JFSmartPtrData {
Data->Ptr = PPtr;
Data->RefCount = 1;
}

JFSmartPtr( JFSmartPtr const &PInstance )
{
Data = PInstance.GetData();
++Data->RefCount;
}

~JFSmartPtr()
{
ReleaseData();
}

void Reset( T *PPtr = NULL )
{
ReleaseData();

Data = new JFSmartPtrData<T>();
Data->Ptr = PPtr;
Data->RefCount = 1;
}

void reset( T *PPtr = NULL )
{
Reset( PPtr );
}

T* GetPtr() const
{
return Data->Ptr;
}

T* get() const
{
return GetPtr();
}

JFSmartPtrData<T>* GetData() const
{
return Data;
}

JFSmartPtr& operator =( JFSmartPtr const &PInstance )
{
ReleaseData();

Data = PInstance.GetData();
++Data->RefCount;

return *this;
}

T* operator ->() const
{
return GetPtr();
}
};

Jonathan


Back to top
Alisdair Meredith [TeamB]
Guest





PostPosted: Tue Dec 06, 2005 5:25 pm    Post subject: Re: smart pointer class Reply with quote

Jonathan Benedicto wrote:

Quote:
Boost is kinda big, and whenever I want to give code to someone, I
don't like to have to tell them to get boost.

Fair enough.
I wonder if we can get Boost to cut out their TR1 implementations as a
separately downloadable library? That might reduce some of the bloat /
intimidation factor.

Quote:
I figured that the user of the class could take care of this, not
knowing that shared_ptr actually was thread-safe.

So long as everyone co-operates, that will work.
Might be nicer if the pointer itself referenced the object to lock, or
you need to pass around the mutex AND the pointer to every call.

And as I said, Boost have an even niftier solution in place now :)


Quote:
ii/ You cannot use incomplete types, so not appropriate for pImpl
idiom

Hmm, I'll have to check that out, thank you.

That fooled me at first too. This is when I started to realise just
how subtle the Boost implementation was (in a good way.)

Quote:
iv/ How will you break cycles, where 2 shared objects have
references to each other

Please could you explain this further.

These classes may be useful for future examples:

struct X { virtual ~X() {} };
struct Y : X {};
struct Z : Y {
shared_ptr< X > m_x;
explicit Z( shared_ptr< X > param ) : m_x( param ) {}
Z() : m_x() {}
};

OK, for (iv)

viod leaks()
{
Z * temp = new Z();
shared_ptr< X > a( temp );
shared_ptr< X > b( new Z( a ) );
temp->m_x = b;
}

Note that all memory is owned by shared pointers.
But as the objects go out of scope, a and b are still maintaining a
reference to each other, so the use count never drops to zero and the
shared_ptrs 'leak'.

Boost shared_ptr allows you to explicitly handle cycles using weak_ptr.
Other smart pointer types even collect the cycles for you.

Quote:
ix/ cannot copy constuct or assign with smart-ptr-to-derived
objects.

I thought that I had a copy constructor. I'll have to go and look
that up.

shared_ptr< X > x;
shared_ptr< Y > y;
x = y; // Different types, so error. Works for raw pointers and boost


I will get back to you later on the implementation details, there are a
few comments to make there as well ;?)


If you want a deeper look into smart pointers, I would take a look at
Andrei Alexandrescu's book 'Modern C++ Design'. It has a much more
involved design than boost. Much more customizable with a very
different set of complexity tradeoffs. The Loki library is also
considerably smaller to download <g>

Personally, I found the sheer complexity of Andrei's design overwelming
in practice, and find tr1::shared_ptr a really nice balance of
customization vs features. I know others have extended Andrei's design
considerably. It is a very good read, and only a single chapter of a
very instructive book.


--
AlisdairM(TeamB)

Back to top
Thomas Maeder [TeamB]
Guest





PostPosted: Tue Dec 06, 2005 6:26 pm    Post subject: Re: smart pointer class Reply with quote

"Jonathan Benedicto" <incorrect (AT) no (DOT) server> writes:

Quote:
Alisdair Meredith [TeamB] wrote:
Experience has shown smart pointer libraries to be extremely subtle
beasts to get exactly right. I hope you have a large library of
tests!

Well, I don't have too many.

One nice thing about the Boost library is that they do.


Quote:
Boost is kinda big, and whenever I want to give code to someone, I
don't like to have to tell them to get boost.

Why don't you give them your code *and* the Boost library?


Quote:
Note that I think writing such a smart pointer IS a very valuable
exercise, you can learn a lot from doing this, I would just think
very carefully before putting it into production use over
shared_ptr. Please don't take the following comments as a
discouragement - more a quick distilling of what I learned looking
at boost implementation over the years:

i/ You have no thread safety here at all (boost now have a very
efficient 'lock free' implementation)

I figured that the user of the class could take care of this, not
knowing that shared_ptr actually was thread-safe.

I'm afraid that this is not going to work.

First, the library has to give the user code the chance to take care
of its part, e.g. by not using objects with static storage duration or
synchronizing accesses to them.

Second, you'll have to decide whether ownership of an object should be
allowed to be shared among different threads. If yes, I'm afraid that
you'll have to add synchronization inside the smart pointer class
itself or things will get "interesting very fast.

And these are just the obvious issues ...


Quote:
iv/ How will you break cycles, where 2 shared objects have references
to each other

Please could you explain this further.

E.g.

// to avoid instantianting JFSmartPtr on an incomplete type
struct Base
{
virtual ~Base() {}
};

struct Derived : Base
{
JFSmartPtr<Base> jfspb;
}

int main()
{
JFSmartPtr<Base> j(new Derived);
j->jfspb = new Derived;
j->jfspb->jfspb = j.get();
}

The two Derived objects will be leaked. That's ok - the will be leaked
if you use boost::shared_ptr, as well. But the question is ceratainly
worth a thought.

Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++) All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.