Topic: Is this a defect?


Author: karima.ratiba@caramail.com (Ratiba&Karima)
Date: Sat, 2 Feb 2002 17:27:34 GMT
Raw View
Alexandre Mah <alexm@cse.unsw.EDU.AU> wrote in message news:<Pine.OSF.4.44.0201310629500.4001-100000@ives.orchestra.cse.unsw.EDU.AU>...
> On Wed, 30 Jan 2002, Michiel Salters wrote:
>
> > Alexandre Mah <alexm@cse.unsw.EDU.AU> wrote in message news:<Pine.GSO.4.44.0201301539540.24039-100000@hummel.orchestra.cse.unsw.EDU.AU>...
> > > It is pretty hard to tell from the specification whether the following
> > > code is safe.
> > >
> > > vector<int> x;
> > > x.push_back(1); x.push_back(2);
> > > x.push_back(x.front());     /* Is this line safe? */
> > >
> > > If push_back() causes reallocation, then all references to members of x
> > > become invalidated.  The reference passed as an argument to the last call
> > > to push_back() is valid before the call to push_back() and is invalid
> > > after the call to push_back() if reallocation occurs, but is it valid
> > > during the call to push_back()?
> >
> > Note that vector<int>::push_back takes an int const&, not an int
> > and push_back(x) is equivalent to insert(end(),x) which works the
> > same.
> >
> > > The relevant section is 23.2.4.  Section 23.1.1 on sequence requirements
> > > appears to suggest that the above code should be safe since the argument
> > > passed to push_back is valid at the point in time when push_back() is
> > > called.  However, section 23.2.4 says that the point in time when the
> > > references to elements of the vector become invalid is when the
> > > reallocation occurs (which presumably is before the value being pushed
> > > gets copied into the newly allocated space).
> >
> > I fail to see where 23.1.1 requires an object to be copied before
> > it is inserted. 23.2.4 is clear, though, and establishes additional
> > requirements. So the code is unsafe.
>
> 23.1.1 does not directly specify when the object needs to be copied, but
> it does specify the behaviour of push_back(), which requires that if
> push_back() is passed a valid reference, then its behaviour is to insert
> the value of its argument at the end of the sequence.  This behaviour
> supposedly should be respected by vector since section 23.2.4 does not
> invalidate this behaviour.
>
> > Not all requirements are repeated in the standard; if one clause
> > invalidates a construct and another clause gives a meaning for a
> > superset, the invalidating clause still holds.
>
> The supposed behaviour of push_back() as defined in 23.1.1 is not at all
> invalidated by 23.2.4.  Section 23.2.4 adds the condition that
> reallocation will invalidate references to elements of the container but
> this does not contradict or change the required behaviour that push_back()
> should insert its argument at the end of the container provided it is
> given a valid argument (and the argument to push_back() in
> "x.push_back(x.front())" is certainly a valid reference at the time the
> call is made).
>
> Because of this, I would tend to think that "x.push_back(x.front())" is
> guaranteed to be safe by the specification.  However, the specification as
> it stands still leaves room for doubt.
>
> I think "x.push_back(x.front())" is quite a common thing to want to do, so
> it might be a good thing for the specification to explicitly guarantee its
> safety.
> As an example, in computational geometry, supposing you have a vector
> containing the points around a polygon, then "x.push_back(x.front())"
> would close the polygon.
>
> Alex
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

I really don'y know whats your problem.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Alexandre Mah <alexm@cse.unsw.EDU.AU>
Date: Wed, 30 Jan 2002 02:07:31 CST
Raw View
It is pretty hard to tell from the specification whether the following
code is safe.

vector<int> x;
x.push_back(1); x.push_back(2);
x.push_back(x.front());     /* Is this line safe? */

If push_back() causes reallocation, then all references to members of x
become invalidated.  The reference passed as an argument to the last call
to push_back() is valid before the call to push_back() and is invalid
after the call to push_back() if reallocation occurs, but is it valid
during the call to push_back()?

The relevant section is 23.2.4.  Section 23.1.1 on sequence requirements
appears to suggest that the above code should be safe since the argument
passed to push_back is valid at the point in time when push_back() is
called.  However, section 23.2.4 says that the point in time when the
references to elements of the vector become invalid is when the
reallocation occurs (which presumably is before the value being pushed
gets copied into the newly allocated space).

So section 23.1.1 implies the above code is safe, whereas 23.2.4, while
not directly implying the above code is unsafe, seems to suggest that the
reference may be invalid at the point in time when the actual copy is
made.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Bernd Strieder <strieder@rhrk.uni-kl.de>
Date: Wed, 30 Jan 2002 08:07:47 CST
Raw View
Alexandre Mah wrote:

> It is pretty hard to tell from the specification whether the following
> code is safe.
>
> vector<int> x;
> x.push_back(1); x.push_back(2);
> x.push_back(x.front());     /* Is this line safe? */
>
> If push_back() causes reallocation, then all references to members of x
> become invalidated.  The reference passed as an argument to the last call
> to push_back() is valid before the call to push_back() and is invalid
> after the call to push_back() if reallocation occurs, but is it valid
> during the call to push_back()?

An implementation could easily make it safe. The actual invalidation
happens when the storage for the old members is deleted. Whenever this
happens after the actual push_back operation in the new storage area, there
is no problem. All member functions possibly reallocating should behave
this way.

I think that actual implementations are already required to behave this way
to maintain exception safety. Destroying anything must not happen before
all crucial things have happened, preparing switching the container to its
new state without any exceptions to occur. So, while the problem might not
be clearly resolved anywhere, it is implied.

Bernd Strieder

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: Wed, 30 Jan 2002 08:26:55 CST
Raw View
Alexandre Mah <alexm@cse.unsw.EDU.AU> wrote in message news:<Pine.GSO.4.44.0201301539540.24039-100000@hummel.orchestra.cse.unsw.EDU.AU>...
> It is pretty hard to tell from the specification whether the following
> code is safe.
>
> vector<int> x;
> x.push_back(1); x.push_back(2);
> x.push_back(x.front());     /* Is this line safe? */
>
> If push_back() causes reallocation, then all references to members of x
> become invalidated.  The reference passed as an argument to the last call
> to push_back() is valid before the call to push_back() and is invalid
> after the call to push_back() if reallocation occurs, but is it valid
> during the call to push_back()?

Note that vector<int>::push_back takes an int const&, not an int
and push_back(x) is equivalent to insert(end(),x) which works the
same.

> The relevant section is 23.2.4.  Section 23.1.1 on sequence requirements
> appears to suggest that the above code should be safe since the argument
> passed to push_back is valid at the point in time when push_back() is
> called.  However, section 23.2.4 says that the point in time when the
> references to elements of the vector become invalid is when the
> reallocation occurs (which presumably is before the value being pushed
> gets copied into the newly allocated space).

I fail to see where 23.1.1 requires an object to be copied before
it is inserted. 23.2.4 is clear, though, and establishes additional
requirements. So the code is unsafe.

Not all requirements are repeated in the standard; if one clause
invalidates a construct and another clause gives a meaning for a
superset, the invalidating clause still holds.

Regards,
--
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Alexandre Mah <alexm@cse.unsw.EDU.AU>
Date: Wed, 30 Jan 2002 14:52:11 CST
Raw View
On Wed, 30 Jan 2002, Michiel Salters wrote:

> Alexandre Mah <alexm@cse.unsw.EDU.AU> wrote in message news:<Pine.GSO.4.44.0201301539540.24039-100000@hummel.orchestra.cse.unsw.EDU.AU>...
> > It is pretty hard to tell from the specification whether the following
> > code is safe.
> >
> > vector<int> x;
> > x.push_back(1); x.push_back(2);
> > x.push_back(x.front());     /* Is this line safe? */
> >
> > If push_back() causes reallocation, then all references to members of x
> > become invalidated.  The reference passed as an argument to the last call
> > to push_back() is valid before the call to push_back() and is invalid
> > after the call to push_back() if reallocation occurs, but is it valid
> > during the call to push_back()?
>
> Note that vector<int>::push_back takes an int const&, not an int
> and push_back(x) is equivalent to insert(end(),x) which works the
> same.
>
> > The relevant section is 23.2.4.  Section 23.1.1 on sequence requirements
> > appears to suggest that the above code should be safe since the argument
> > passed to push_back is valid at the point in time when push_back() is
> > called.  However, section 23.2.4 says that the point in time when the
> > references to elements of the vector become invalid is when the
> > reallocation occurs (which presumably is before the value being pushed
> > gets copied into the newly allocated space).
>
> I fail to see where 23.1.1 requires an object to be copied before
> it is inserted. 23.2.4 is clear, though, and establishes additional
> requirements. So the code is unsafe.

23.1.1 does not directly specify when the object needs to be copied, but
it does specify the behaviour of push_back(), which requires that if
push_back() is passed a valid reference, then its behaviour is to insert
the value of its argument at the end of the sequence.  This behaviour
supposedly should be respected by vector since section 23.2.4 does not
invalidate this behaviour.

> Not all requirements are repeated in the standard; if one clause
> invalidates a construct and another clause gives a meaning for a
> superset, the invalidating clause still holds.

The supposed behaviour of push_back() as defined in 23.1.1 is not at all
invalidated by 23.2.4.  Section 23.2.4 adds the condition that
reallocation will invalidate references to elements of the container but
this does not contradict or change the required behaviour that push_back()
should insert its argument at the end of the container provided it is
given a valid argument (and the argument to push_back() in
"x.push_back(x.front())" is certainly a valid reference at the time the
call is made).

Because of this, I would tend to think that "x.push_back(x.front())" is
guaranteed to be safe by the specification.  However, the specification as
it stands still leaves room for doubt.

I think "x.push_back(x.front())" is quite a common thing to want to do, so
it might be a good thing for the specification to explicitly guarantee its
safety.
As an example, in computational geometry, supposing you have a vector
containing the points around a polygon, then "x.push_back(x.front())"
would close the polygon.

Alex

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]