Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, February 2007
QSharedDataPointer problems - destructor called more than once?


Message 1 in thread

Hi all.  Having the following issue, which seems to happen  
inconsistently.

I have a QSharedDataPointer that points to an object that inherits  
QSharedData.  I'm emitting a signal that contains the pointer as  
follows:

emit mySignal( QSharedDataPointer< MyData >( new MyData() ) );

On the receiving end, I have a slot that takes the pointer:
mySlot( QSharedDataPointer< MyData > );

For some reason, on occasion, I notice that ~MyData() gets called  
twice, which corrupts memory, because MyData has a pointer member  
that points to a single memory location (and must do so).

Does emitting this as a signal result in a detach() somewhere that  
gives us this behavior?  If so, then why is this only happening on  
occasion?

Is there a better approach to what I'm trying to accomplish - I'd  
like for several objects who deal with this data via their slots to  
deal with the same data, and for that data only to be destroyed when  
1) the slot/signal system has delivered the signal to all the slots  
and 2) those slots have finished working with the data.  Also the  
object that emits the signal is stateless and cannot keep track of  
this data itself.

Thanks,
Bruno






Message 2 in thread

So I did a quick experiment.  I have a slot accepting the  
QSharedDataPointer as an argument.  Let's call it:
void MySlot( QSharedDataPointer < MyData > in_d )

The first thing I do is output the ref count:
cout << in_d->ref << endl;

Then I create a new Pointer, passing it the original one:
QSharedDataPointer<MyData> d(in_d); // QSharedDataPointer<MyData> d =  
in_d;  // <- I've also tried this variation

Then I print out the ref count for both of the two pointers:
cout << in_d->ref << endl;
cout << d->ref << endl;

In all cases, what I see is:
1
1
1

The ref count never increases!  Can someone please lend some insight  
- I'm stumped and nothing in the docs is clarifying this for me.  I'm  
uising Qt on Mac OS X (Intel), linked against Qt frameworks.

Thanks,
Bruno


On Feb 2, 2007, at 10:57 AM, Bruno Trindade wrote:

> Hi all.  Having the following issue, which seems to happen  
> inconsistently.
>
> I have a QSharedDataPointer that points to an object that inherits  
> QSharedData.  I'm emitting a signal that contains the pointer as  
> follows:
>
> emit mySignal( QSharedDataPointer< MyData >( new MyData() ) );
>
> On the receiving end, I have a slot that takes the pointer:
> mySlot( QSharedDataPointer< MyData > );
>
> For some reason, on occasion, I notice that ~MyData() gets called  
> twice, which corrupts memory, because MyData has a pointer member  
> that points to a single memory location (and must do so).
>
> Does emitting this as a signal result in a detach() somewhere that  
> gives us this behavior?  If so, then why is this only happening on  
> occasion?
>
> Is there a better approach to what I'm trying to accomplish - I'd  
> like for several objects who deal with this data via their slots to  
> deal with the same data, and for that data only to be destroyed  
> when 1) the slot/signal system has delivered the signal to all the  
> slots and 2) those slots have finished working with the data.  Also  
> the object that emits the signal is stateless and cannot keep track  
> of this data itself.
>
> Thanks,
> Bruno
>
>
>
>
>



Message 3 in thread

On Friday 02 February 2007 22:19, Bruno Trindade wrote:
> So I did a quick experiment.  I have a slot accepting the
> QSharedDataPointer as an argument.  Let's call it:
> void MySlot( QSharedDataPointer < MyData > in_d )
>
> The first thing I do is output the ref count:
> cout << in_d->ref << endl;
>
> Then I create a new Pointer, passing it the original one:
> QSharedDataPointer<MyData> d(in_d); // QSharedDataPointer<MyData> d =
> in_d;  // <- I've also tried this variation
>
> Then I print out the ref count for both of the two pointers:
> cout << in_d->ref << endl;
> cout << d->ref << endl;
>
> In all cases, what I see is:
> 1
> 1
> 1
>
> The ref count never increases!  Can someone please lend some insight
> - I'm stumped and nothing in the docs is clarifying this for me.  I'm
> uising Qt on Mac OS X (Intel), linked against Qt frameworks.
>
> Thanks,
> Bruno
>

As the name of the class says, it is a shared data pointer. It basically means 
that you will have the same object as long as you don't modify the data. When 
you try to modify the shared data object, you get a deep copy of it. In your 
case the compiler has no idea that you don't want to modify the data since 
you pass it to a function where it could be modified. When you dereference 
the pointer, you tell to the compiler that you may want to modify it even if 
you don't do it.

The QSharedDataPointer is good for resources that are shared along many users 
without ever modifying it, like QFont that stays the same unless you replace 
it with something else in the specific widget. One possible option could be 
changing your slot functions to take a const QSharedDataPointer argument. 
That should tell to the compiler that you will not change the data object in 
your function, but I haven't tried that approach myself.

I went another way and implemented my own reference counted objects, which 
works perfect for my needs. I can send pointers to my data objects in Qt 
events and be sure that they get deleted when nobody needs them anymore. 
Might be that you could do the same.


Regards,
Enar

--
 [ signature omitted ] 

Message 4 in thread

Thanks Enar.  I was initially going to create my own smart pointers,  
but I didn't want to reinvent the wheel if Qt already offers  
something along this line.  Also, since I'm just starting to learn  
Qt, I thought it worthwhile to invest the time in figuring out how to  
use these built-in classes.

I will try the const approach, and if that fails, I'll go with my  
custom smart pointers.

Thanks again,
Bruno


On Feb 2, 2007, at 4:54 PM, Enar Väikene wrote:

> On Friday 02 February 2007 22:19, Bruno Trindade wrote:
>> So I did a quick experiment.  I have a slot accepting the
>> QSharedDataPointer as an argument.  Let's call it:
>> void MySlot( QSharedDataPointer < MyData > in_d )
>>
>> The first thing I do is output the ref count:
>> cout << in_d->ref << endl;
>>
>> Then I create a new Pointer, passing it the original one:
>> QSharedDataPointer<MyData> d(in_d); // QSharedDataPointer<MyData> d =
>> in_d;  // <- I've also tried this variation
>>
>> Then I print out the ref count for both of the two pointers:
>> cout << in_d->ref << endl;
>> cout << d->ref << endl;
>>
>> In all cases, what I see is:
>> 1
>> 1
>> 1
>>
>> The ref count never increases!  Can someone please lend some insight
>> - I'm stumped and nothing in the docs is clarifying this for me.  I'm
>> uising Qt on Mac OS X (Intel), linked against Qt frameworks.
>>
>> Thanks,
>> Bruno
>>
>
> As the name of the class says, it is a shared data pointer. It  
> basically means
> that you will have the same object as long as you don't modify the  
> data. When
> you try to modify the shared data object, you get a deep copy of  
> it. In your
> case the compiler has no idea that you don't want to modify the  
> data since
> you pass it to a function where it could be modified. When you  
> dereference
> the pointer, you tell to the compiler that you may want to modify  
> it even if
> you don't do it.
>
> The QSharedDataPointer is good for resources that are shared along  
> many users
> without ever modifying it, like QFont that stays the same unless  
> you replace
> it with something else in the specific widget. One possible option  
> could be
> changing your slot functions to take a const QSharedDataPointer  
> argument.
> That should tell to the compiler that you will not change the data  
> object in
> your function, but I haven't tried that approach myself.
>
> I went another way and implemented my own reference counted  
> objects, which
> works perfect for my needs. I can send pointers to my data objects  
> in Qt
> events and be sure that they get deleted when nobody needs them  
> anymore.
> Might be that you could do the same.
>
>
> Regards,
> Enar
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx  
> with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ]