|
Boost : |
Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-22 15:09:54
On Fri, Oct 22, 2010 at 1:35 PM, Daniel Walker
<daniel.j.walker_at_[hidden]> wrote:
> Oops. Sorry, I spoke too soon. In fact, it IS currently possible for a
> boost::function object to become empty due to a failed assignment. It
> happens because the small object manager clones the target during a
> call to swap(). If there is an exception during the allocation,
> boost::function handles it, sets itself to empty and rethrows. Here's
> an example that demonstrates the behavior.
One more thing, for those who are interested. To make the example
portable, you need to add a destructor to S1. Also, so as not to cause
confusion, I should have had operator new actually allocate something.
:P So, to reproduce the behavior the following is a complete example
that works on msvc 10 and gcc 4.2.
#include <cassert>
#include <iostream>
#include <boost/function.hpp>
struct S0 {
void operator()() {}
};
int i = 0;
struct S1 {
~S1() {}
void operator()() {}
void* operator new(std::size_t, void* p)
{
// throw on third alloc
if(++i == 3)
throw std::bad_alloc();
return p = ::new S1();
}
};
int main()
{
boost::function<void()> g = S0();
assert(g); // assertion ok, since g is not empty.
try {
g = S1();
}
catch(std::exception& e) {
std::cerr << "failed function assignment: "
<< e.what() << std::endl;
}
assert(g); // now assert fails, since g is empty.
return 0;
}
Daniel Walker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk