Boost logo

Boost Users :

Subject: Re: [Boost-users] [assign][ptr_container] Exception safety of ptr_list_of, ptr_push_back, ptr_map_insert, etc.
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2014-09-24 20:47:32


On 24/09/2014 21:52, Aaron Levy wrote:
> Yes I saw that the documentation says these are exception safe and
understandably the arguments are forwarded to the constructors. I was
just trying to understand the scenarios under which code like the
example below cause exception-safety issues.
>
> boost::ptr_vector<Foo> vec;
> push_back(vec)(new Foo)(new Foo);
>
> My reasoning was that the nth "new Foo" gets evaluated after the n-1
"new Foo" expressions which by then are already part of the container.

That is not correct. The compiler is free to evaluate the independent
subexpressions in any order; it is only constrained by dependent
expressions. For example, the below code is a valid rewrite of the
above by the compiler internals:

boost::ptr_vector<Foo> vec;
Foo *tmp2 = new Foo;
auto tmp3 = push_back(vec);
Foo *tmp1 = new Foo;
auto tmp4 = tmp3(tmp1);
tmp4(tmp2);

In particular note that if the second "new Foo" (to tmp1) throws --
which is possible due to out-of-memory even if for no other reason --
then the pointer in tmp2 will be leaked, as it hasn't yet been assigned
to the container. The same can occur if push_back or if tmp3() throw.

The compiler is free to allocate tmp1 and tmp2 in any order; the only
constraints are:

1. It must call their constructors after the constructor of vec is called.
2. It must create tmp1 before it can call tmp3 to create tmp4.
3. It must create tmp2 before it can call tmp4.

Similarly if there were any parameters being passed to the Foo
constructor (whether using this method or using constructor forwarding),
temporary values for these could be created in any order -- not just out
of parameter order but also not in the order of constructing the objects
they're being passed to.

It's the same principle as this:

   f(a(), b(), c(), d());

In the above, the compiler can call a,b,c,d in any order. The only
constraint is that it must call all four of them before it can call f.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net