This is with Visual Studio 2012.
static void func(
...,
const std::vector<std::string> &opt_extra_args_strs,
...)
{
// THIS ASSERTS: "vector iterators incompatible"
for (const std::string &arg_str : opt_extra_args_strs) {
... body does not modify opt_extra_args_strs
// BUT THIS WORKS:
for (size_t a_ix = 0; a_ix < opt_extra_args_strs.size(); a_ix++) {
const std::string &arg_str = opt_extra_args_strs[a_ix];
}
I am not modifying the vector at all in the loop body, and in fact, the assertion happens before the first iteration. The vector looks right in the debugger, but I don't know enough about STL to look for corruption. Inside the STL the assertion failure comes from:
void _Compat(const _Myiter& _Right) const {
// test for compatible iterator pair
if (this->_Getcont() == 0 // THIS FAILS (_Getcont() == 0)
...) {
_DEBUG_ERROR("vector iterators incompatible");
with this->_Getcont()
being NULL because (_Myproxy
is NULL in the _Iterator_base12
).
The call stack is:
msvcp110d.dll!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
Main.exe!std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >::_Compat(const std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > > & _Right)
Main.exe!std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >::operator==(const std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > > & _Right)
Main.exe!std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > >::operator!=(const std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > > & _Right)
Main.exe!run_test(..., const std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > & opt_extra_args_strs)
...
I suspect the code setting up the vector is screwing it up somehow, but I am not sure. I am having difficulty writing a simpler reproducer as well, but the program should be totally deterministic (single threaded, not random variables, always asserts).
Additionally, I also run into a different similar assertion failure earlier "vector iterator + offset out of range"
with the snippet (on the same vector)
template <typename T>
class Elsewhere {
virtual void earlier(
....
std::vector<T> &v) const
{
v.emplace_back(); // empty construction of a T
// T &t = v.back(); // assertion failure
T &val = to[to.size() - 1]; // but this works
... mutates val.
With T = std::string
(in fact, the same vector).
I mention this because within STL the condition for this failure ends up also being this->_Getcont() == 0
, and I suspect them to be related. What does it mean for _Getcont()
to be 0 in a Vector_const_iterator
?
The vector comes out of a container
template <typename T>
struct type {
T m_value;
operator const T &() const {
return value();
}
const T &value() const {
return m_value;
}
};
type<std::vector<std::string>> &t = ... method call that returns ref to it;
... t gets set
func(t); // implicit conversion to (const std::vector<std::string> &)
I finally found the problem. A path deep in the vector's setup code was clobbering the vector's state (memset'ing it to 0's as part of a larger chunk of memory). This caused no harm for the first three fields in vector: _Myfirst
, _Mylast
, and _Myend
since those fields are 0 in an initial vector. Moreover, most things such as the array index operator and other methods such as push_back still functioned correctly. However, the fourth field _Myproxy
was initially non-zero, and clearing it disabled iterator-based functionality. Hence, for-each loop, vector::back()
, and others all fail with different false errors such as false bounds checks, false incompatible iterators, etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With