string::iterator should have more error checking
Jonathan Wakely
jwakely@redhat.com
Thu Jun 23 21:26:27 GMT 2022
On Thu, 23 Jun 2022 at 22:05, Frederick Virchanza Gotham via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> If a program is compiled with "-D_GLIBCXX_DEBUG", I would expect it at
> runtime to catch the error on the last line in the following program:
>
> #include <iostream>
> #include <string>
> #include <string_view>
> #include <type_traits>
>
> using namespace std;
>
> int main(void)
> {
> cout << "string::const_iterator is "
> << (is_same_v< string::const_iterator, char const * > ? "just
> a raw pointer" : "NOT a simple pointer") << endl;
>
> cout << "string_view::const_iterator is "
> << (is_same_v< string_view::const_iterator, char const * > ?
> "just a raw pointer" : "NOT a simple pointer") << endl;
>
> string s("brush");
>
> cout << string_view( &*(s.cbegin() + 1u), &*(s.cend() + 876u) ) << endl;
> }
>
>
> string::iterator is NOT a simple pointer -- it is a class and so we
> can overload the following operators to catch errors:
>
> (1) unary operator*
> (2) binary operator+
> (3) binary operator-
>
> The error on the last line of the above program would be caught at
> runtime if the iterator were written as follows:
>
> class string {
>
> class iterator {
>
> char const *const p_min, *const p_max; // initialised in constructor
>
> char *p;
>
> public:
>
> iterator &operator+(ptrdiff_t const n)
> {
> assert( p+n >= p_min );
> assert( p+n <= p_max );
>
> // more code here
> }
> };
> };
I don't think it would be a good idea to do it like this when we
already have an entire Debug Mode framework for handling iterator
validity. You can see how that handles your exmples by repalcing
std::string with __gnu_debug::string (defined in <debug/string>).
> Similarly the unary operator* could be overloaded to catch the error
> when "end()" gets dereferenced.
The lack of iterator checking is documented at
https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_semantics.html
and unlikely to change now. IIRC the main reasons for not adding
iterator checking to std::string were that it would hurt performance,
and that most std::string operations aren't done with iterators
anyway. As soon as you use c_str() or data() to get a raw pointer,
there's nothing that checked iterators can do.
AddressSanitizer does give an error for your example though.
More information about the Libstdc++
mailing list