
Hello group! We are experiencing problems with boost::weak_ptr in a multi-threaded environment. It looks that the lock on the ref counting doesn't work well with weak_ptr in release build. configuration : Windows 2000 SP4 VC6 SP5 boost 1.33.1 In summary, it seems that add_ref_lock in sp_counted_base_w32.hpp has a bug in release. In disassemblies, we observe : 01 lea esi,[eax+4] 02 mov eax,dword ptr [esi] 03 test eax,eax 04 je TestWeakPtr+0E4h (00401244) 05 lea ecx,[eax+1] 06 mov edx,esi 07 lock cmpxchg dword ptr [edx],ecx 08 mov ecx,eax 09 cmp ecx,eax 10 je TestWeakPtr+7Dh (004011dd) At line 08, you'll see that we move eax into ecx and after (line 09) we compare ecx and eax that are obviously the same which will destruct prematurely our pointer. In attachement, I send a complete program reproducing the bug with VC6 in release. It is probably a bug in VC6. But is it caused by a bad use? is it simply a "bug" in boost 1.33.1? By the way, we can remove the "bug" by simply "patching" add_ref_lock implementation like this : bool add_ref_lock() // true on success { for( ;; ) { long tmp = static_cast< long const volatile& >( use_count_ ); if( tmp == 0 ) return false; long tmp2 = tmp + 1; if(InterlockedCompareExchange ( &use_count_, tmp2, tmp ) == tmp2 - 1) return true; } } Thank you for any suggestion! -- Alain Cormier alain.work@gmail.com

Alain Cormier wrote:
Hello group!
We are experiencing problems with boost::weak_ptr in a multi-threaded environment. It looks that the lock on the ref counting doesn't work well with weak_ptr in release build.
configuration : Windows 2000 SP4 VC6 SP5 boost 1.33.1
In summary, it seems that add_ref_lock in sp_counted_base_w32.hpp has a bug in release. In disassemblies, we observe :
01 lea esi,[eax+4] 02 mov eax,dword ptr [esi] 03 test eax,eax 04 je TestWeakPtr+0E4h (00401244) 05 lea ecx,[eax+1] 06 mov edx,esi 07 lock cmpxchg dword ptr [edx],ecx 08 mov ecx,eax 09 cmp ecx,eax 10 je TestWeakPtr+7Dh (004011dd)
At line 08, you'll see that we move eax into ecx and after (line 09) we compare ecx and eax that are obviously the same which will destruct prematurely our pointer. In attachement, I send a complete program reproducing the bug with VC6 in release.
It is probably a bug in VC6. But is it caused by a bad use? is it simply a "bug" in boost 1.33.1?
It seems that the VC6 optimizer doesn't know that the InterlockedCompareExchange intrinsic:
07 lock cmpxchg dword ptr [edx],ecx 08 mov ecx,eax
destroys eax. I'm not sure how to fix this reliably without using a .cpp file.

So, can I conclude that it is a bad behavior in boost::weak_ptr? For now, I
have simply changed add_ref_lock to :
long tmp2 = tmp + 1;
if(InterlockedCompareExchange ( &use_count_, tmp2, tmp ) == tmp2 - 1 )
return true;
This way, VC6 doesn't optimise the return value of
InterlockedCompareExchange and the disassembly looks ok. Can I expect this
workaround (or any better) in boost in a near future so that weak_ptr truly
work with VC6 in release and multi-threaded environment?
Thank you,
Alain
On 4/18/06, Peter Dimov
Alain Cormier wrote:
Hello group!
We are experiencing problems with boost::weak_ptr in a multi-threaded environment. It looks that the lock on the ref counting doesn't work well with weak_ptr in release build.
configuration : Windows 2000 SP4 VC6 SP5 boost 1.33.1
In summary, it seems that add_ref_lock in sp_counted_base_w32.hpp has a bug in release. In disassemblies, we observe :
01 lea esi,[eax+4] 02 mov eax,dword ptr [esi] 03 test eax,eax 04 je TestWeakPtr+0E4h (00401244) 05 lea ecx,[eax+1] 06 mov edx,esi 07 lock cmpxchg dword ptr [edx],ecx 08 mov ecx,eax 09 cmp ecx,eax 10 je TestWeakPtr+7Dh (004011dd)
At line 08, you'll see that we move eax into ecx and after (line 09) we compare ecx and eax that are obviously the same which will destruct prematurely our pointer. In attachement, I send a complete program reproducing the bug with VC6 in release.
It is probably a bug in VC6. But is it caused by a bad use? is it simply a "bug" in boost 1.33.1?
It seems that the VC6 optimizer doesn't know that the InterlockedCompareExchange intrinsic:
07 lock cmpxchg dword ptr [edx],ecx 08 mov ecx,eax
destroys eax.
I'm not sure how to fix this reliably without using a .cpp file.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Alain Cormier wrote:
So, can I conclude that it is a bad behavior in boost::weak_ptr?
No, it is a bug in VC6.
For now, I have simply changed add_ref_lock to :
long tmp2 = tmp + 1; if(InterlockedCompareExchange ( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
This way, VC6 doesn't optimise the return value of InterlockedCompareExchange and the disassembly looks ok.
I don't think that there is any guarantee that this modification will reliably produce correct code, even if it happens to work in the examples we try. But if we can't think of a better way to work around the issue, this may be our best bet.

Alain Cormier wrote:
So, can I conclude that it is a bad behavior in boost::weak_ptr? For now, I have simply changed add_ref_lock to :
long tmp2 = tmp + 1; if(InterlockedCompareExchange ( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
This way, VC6 doesn't optimise the return value of InterlockedCompareExchange and the disassembly looks ok. Can I expect this workaround (or any better) in boost in a near future so that weak_ptr truly work with VC6 in release and multi-threaded environment?
I have applied your fix. It will be included in the upcoming release 1.34. Thanks for the report!
participants (2)
-
Alain Cormier
-
Peter Dimov