Topic: Defect Report : Is it undefined if a function in the standard changes
Author: chris jefferson <caj@cs.york.ac.uk>
Date: Wed, 14 Sep 2005 15:14:38 +0000 (UTC) Raw View
[ Note: Forwarded to C++ Committee. -sdc ]
Problem: There are a number of places in the C++ standard library where
it is possible to write what appear to be sensible ways of calling
functions, but which can cause problems in some (or all)
implementations, as they cause the values given to the function to be
changed in a way not specified in standard (and therefore not coded to
correctly work). These fall into two similar categories.
1) Parameters taken by const reference can be changed during execution
of the function
Examples:
Given std::vector<int> v:
v.insert(v.begin(), v[2]);
v[2] can be changed by moving elements of vector
Given std::list<int> l:
l.remove(*l.begin());
Will delete the first element, and then continue trying to access it.
This is particularily vicious, as it will appear to work in almost all
cases.
2) A range is given which changes during the execution of the function:
Similarly,
v.insert(v.begin(), v.begin()+4, v.begin()+6);
This kind of problem has been partly covered in some cases. For example
std::copy(first, last, result) states that result cannot be in the range
[first, last). However, does this cover the case where result is a
reverse_iterator built from some iterator in the range [first, last)?
Also, std::copy would still break if result was reverse_iterator(last +
1), yet this is not forbidden by the standard
Solution:
One option would be to try to more carefully limit the requirements of
each function. There are many functions which would have to be checked.
However as has been shown in the std::copy case, this may be difficult.
A simpler, more global option would be to somewhere insert text similar to:
If the execution of any function would change either any values passed
by reference or any value in any range passed to a function in a way not
defined in the definition of that function, the result is undefined.
Such code would have to at least cover chapters 23 and 25 (the sections
I read through carefully). I can see no harm on applying it to much of
the rest of the standard.
Some existing parts of the standard could be improved to fit with this,
for example the requires for 25.2.1 (Copy) could be adjusted to:
Requires: For each non-negative integer n < (last - first), assigning to
*(result + n) must not alter any value in the range [first + n, last).
However, this may add excessive complication.
One other benefit of clearly introducing this text is that it would
allow a number of small optimisations, such as caching values passed
by const reference.
Chris
[ 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.jamesd.demon.co.uk/csc/faq.html ]