Boost logo

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