Add checks for invalid iterator when _ITERATOR_DEBUG_LEVEL is non-zero#3282
Conversation
You can link properly, just change your message to |
|
Really strange. Look at my message: #3276 (comment) |
|
Oh, my bad. |
Ach, and I didn't notice either. Now changed and working properly. Thank you! |
| #if _ITERATOR_DEBUG_LEVEL != 0 | ||
| const auto _Mycont = static_cast<const _Myvec*>(this->_Getcont()); | ||
| _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); | ||
| _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); |
There was a problem hiding this comment.
Doesn't this subsume the previous line? Can we just check for _STL_VERIFY(_Mycont and not check for _Ptr as well?
There was a problem hiding this comment.
Well, we could but I think there is a useful distinction to retain between attempting to dereference a value initialized vector iterator and attempting to dereference an invalidated iterator.
There was a problem hiding this comment.
Ah, and additionally I believe _Mycont is only cleared at _ITERATOR_DEBUG_LEVEL of 2, so the check would be lost at level 1.
strega-nil-ms
left a comment
There was a problem hiding this comment.
I don't know enough about iterator debugging checks to say, but this does seem extremely reasonable. I would like someone who's been on the project longer than me to take a look, though.
CaseyCarter
left a comment
There was a problem hiding this comment.
In the past we've simply allowed these cases to crash by dereferencing a null _Mycont, but reporting specific error messages is probably much more digestible for non-expert users. Thanks Roger!
|
As @CaseyCarter noted, we previously removed a lot of our "we're about to dereference null" debugging checks because null dereferences are fairly easy to understand. I agree that it makes sense to add null checks here to help users, because these null dereferences are special - they would occur in our debugging machinery itself. I also checked, and in other containers we always test I noticed that there's one remaining case: Lines 101 to 115 in 4483e87 This is used by #include <cstdio>
#include <vector>
using namespace std;
int main() {
vector<int>::iterator it;
{
vector<int> vec{11, 22, 33};
it = vec.begin();
}
puts("Running it += 0;");
it += 0;
puts("... done.");
puts("Running it += 1;");
it += 1;
puts("... done. (UH OH)");
puts("Running it += -1;");
it += -1;
puts("... done. (ALSO UH OH)");
}(Seeking an invalidated iterator by zero is technically bogus, but it's debatable whether we should complain here. Seeking by nonzero is super bogus.) Ordinarily I would simply push changes to handle this case, but that might cause our Contributor License Agreement bot to ask you to agree to our CLA (it appears to have a de minimis threshold for tiny changes like a 5-line PR, but it'll ask for larger PRs). While our CLA is totally cool, on rare occasions it makes someone nervous, so I prefer to avoid pushing small PRs from new contributors over the limit if we can avoid it. As this PR is a strict improvement, I think we can merge it as-is, and I've recorded a todo to update |
I'd be fine with signing it; Iwas expecting it to trigger when I raised the P/R and wondered whether it was suppressed by the prior NDA I'd signed with MS
Agree. Dereferencing is also I suspect more common than invoking operator+= |
|
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
|
Thanks for improving these runtime diagnostics, and congratulations on your first microsoft/STL commit! 🎉 🚀 😸 This will be available in VS 2022 17.6 Preview 1. |
|
I don't have a minimal reproduction case yet, though this trips when using Clang in debug builds, where MSVC does not |
@pbdot We have encountered this issue on clang 16 in the xtensor project as well. |
fixes #3281