weak_ptr::lock crashes when the code is compiled with the -fno-exceptions flag and the data pointed by the weak_ptr expires during the execution of the lock function itself:
494 lock() const noexcept
496 #ifdef __GTHREADS
497 if (this->expired())
498 return shared_ptr<_Tp>();
502 return shared_ptr<_Tp>(*this);
504 __catch(const bad_weak_ptr&)
506 return shared_ptr<_Tp>();
509 return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
If the data is valid when line 497 is executed and the data is released in a different thread just before executing line 502, the program will crash because it will try to throw an exception (exceptions are disabled because of the flag -fno-exceptions). This code only works when exceptions are enabled because the try/catch will resolve the problem, but not otherwise.
The standard definition says that this function must return safely and it doesn't throw any exception. I presume this must apply even if the exceptions are not enabled.
The standard says exceptions are always enabled, if you disable them you are no longer using standard C++, so what it says in the standard doesn't necessarily apply.
I don't think it would be simple to make this work with -fno-exceptions
(In reply to Jonathan Wakely from comment #1)
> The standard says exceptions are always enabled, if you disable them you are
> no longer using standard C++, so what it says in the standard doesn't
> necessarily apply.
It's a quality of implementation issue: effectively current std::weak_ptr is not usable in any multithreaded program built with -fno-exceptions.
> I don't think it would be simple to make this work with -fno-exceptions
We have a patch that makes it work.
*** Bug 59869 has been marked as a duplicate of this bug. ***
Created attachment 31911 [details]
Copy of test case from PR 59869
Thanks Paul. You mentioned a proposed patch, are you working on that? From a quick look I didn't see how to fix it without adding a _Sp_counted_base::_M_add_ref_lock_nothrow() function and adding new constructors taking an additional std::nothrow_t argument to the whole class hierarchy. Did you have a simpler fix in mind?
Created attachment 31920 [details]
don't use _M_add_ref_lock() when exceptions are disabled
Here's a patch which fixes Paul's testcase
Created attachment 31924 [details]
Alternate fix from Kyle Lippincott
Alternate patch, courtesy Kyle Lippincott <firstname.lastname@example.org>.
AFAIU, Kyle's patch uses roughly the same idea as Jonathan's,
but no #ifdef's.
Should we take these patches to gcc-patches list?
Thanks, yes the general idea is identical. I prefer some parts of Kyle's fix but I don't want the new constructor to be public, so I'll combine the two patches and post it to gcc-patches next week.
Date: Tue Jan 28 10:23:27 2014
New Revision: 207180
2014-01-28 Jonathan Wakely <email@example.com>
Kyle Lippincott <firstname.lastname@example.org>
* include/bits/shared_ptr.h (shared_ptr): Add new non-throwing
constructor and grant friendship to weak_ptr.
(weak_ptr::lock()): Use new constructor.
(_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function
and define specializations.
(__shared_count): Add new non-throwing constructor.
(__shared_ptr): Add new non-throwing constructor and grant friendship
(__weak_ptr::lock()): Use new constructor.
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
Fixed on trunk
Date: Tue Jan 28 19:08:00 2014
New Revision: 207201
For Google b/12533273 and PR 59656, partially backport r207180 from trunk.
(The new test: libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
is not added, because it succeeds to compile with gcc-4_8.)