-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Description
When iterator debugging is enabled and a vector iterator is invalidated, for example by a call to erase at or before the referenced element, an attempt to dereference the iterator causes an access violation.
Command-line test case
C:\Temp>type repro.cpp
#include <vector>
int main() {
std::vector<int> v({0,1,2,3});
auto iter = v.begin();
v.erase(v.begin()); // invalidate iter
return *iter; // access violation, rather than an assertion
}
c:\temp>cl /EHsc /Zi /MDd repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31935 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
repro.cpp
Microsoft (R) Incremental Linker Version 14.34.31935.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
/debug
repro.obj
c:\temp>repro
c:\temp>echo %ERRORLEVEL%
-1073741819
c:\temp>
The error code is that of STATUS_ACCESS_VIOLATION 0xC0000005 ("The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.").
Expected behavior
I was hoping to have an assert failure from the iterator dereference in <vector>.
What happens is an access violation.
The affected code is:
45 _NODISCARD _CONSTEXPR20 reference operator*() const noexcept {
46 #if _ITERATOR_DEBUG_LEVEL != 0
47 const auto _Mycont = static_cast<const _Myvec*>(this->_Getcont());
48 _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator");
49 _STL_VERIFY(
50 _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator");
51 #endif // _ITERATOR_DEBUG_LEVEL != 0
52
53 return *_Ptr;
54 }
The AV occurs at line 49/50 as _Mycont is null; this is becasue the call to erase that invalidated the iterator changed the fields in the base class _Iterator_base12 to reflect this, such that _Getcont() now returns null by design:
In <vector>:
2216 } else { // orphan the iterator
2217 _Temp->_Myproxy = nullptr;
STL version
Microsoft Visual Studio Community 2022 (64-bit) - Current
Version 17.4.2
Possible Proposed Resolution
Add a new line between lines 48 and 49:
_STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator");
The check takes place after the check on _Ptr, which detects ''uninitialised'' iterators, and before the problematic dereference of _Mycont.
A similar additional line could be added to other methods which perform similar checking, such as operator->.
I'm raising a P/R ...