2

The assignment of a default constructed vector<int*>::const_iterator errors on Visual Studio 2010. I've tried this on 5 Visual Studio 2010 systems that all have Service Pack 1. It fails on 3/5 machines, I've been able to identify what is causing the failure on the 3 systems but I cannot seem to find a bug report.

Here is the code:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int*> vec;
    int arr[3] = {};

    for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) vec.push_back(arr + i);

    vector<int*>::const_iterator initialized = vec.cbegin();
    vector<int*>::const_iterator uninitialized;

    initialized = uninitialized;

    cout << "Hello World" << endl;

    return 0;
}

Clearly everything but the cout << "Hello World" << endl; is optimized out in Release so this minimal example will only fail in Debug. But in Debug the error it gives is:

Unhandled exception at 0x01071e14 in test.exe: 0xC0000005: Access violation reading location 0x00000000.

Comparing the working and non-working MSVCP100D.dlls that were linked shows that there is a slight discrepancy, the working .dll is Product Version: 10.0.40219.325 and the non-working .dll is Product Version: 10.0.40219.1.

The actual error occurs in

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xutility

And again diffing the working and non-working version shows that a change has been made to the working version. The non-working code simply says:

if (_Myproxu != _Right._Myproxy)
    _Adopt(_Right._Myproxy->_Mycont);

The working code says:

if (_Myproxy == _Right._Myproxy)
    ;
else if (_Right._Myproxy != 0)
    _Adopt(_Right._Myproxy->_Mycont);
else
    {   // becoming invalid, disown current parent
    _Lockit _Lock(_LOCK_DEBUG);
    _Orphan_me();
    }

All that to say, here's my actual question. How do I get this update? I've updated to the latest using Windows Update, but the problem has not been resolved. Is there some hidden patch that I need to go somewhere to get? I can't find this issue written up anywhere, so I also can't find information about the patch.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    @JamesAdkison, you clearly do. There is nothing wrong in HAVING unititialized iterator, as long as it is not dereferenced. As for why, it is easy to see how this can happen when iterators are members of some objects, and one object (which was initialized in a certain way) is assigned to another, which was not. – SergeyA Sep 23 '15 at 20:41
  • 1
    @JamesAdkison, I am not an OP, so I am not sure what he is trying to do. But, taking the post at the face value (I have no means to verify it) the code provided should not crash program. If it does, it is a bad implementation bug. I was trying to see when this might happen in real life, as obviously code posted is demonstrational. And I am not sure what you mean by 'mixing'. You are not supposed to compare those iterators, of course. But there is nothing wrong in assigning them to each other. – SergeyA Sep 23 '15 at 20:49
  • @SergeyA Well said. In my actual code the `const_iterator` is an object member. So assignment of one of my default constructed objects will cause this assignment to happen. As you say there's nothing wrong with this, but I can't get my hands on a patch. And I'm loathe to say that I am considering stomping the non-working files with working files. Which is a truly terrible plan. – Jonathan Mee Sep 23 '15 at 21:09
  • Sorry, can't be of any help here. Know almost nothing of Windows compilers. You might want to reach out to folks working for Microsoft and having blogs and as this in comments to unrelated posts :). Probably, http://blogs.msdn.com/b/vcblog/ would be a place to start? – SergeyA Sep 23 '15 at 21:15
  • 1
    I'm fairly sure this is technically UB. `uninitialized` is singular, and [iterator.requirements.general]/p6 makes clear that "Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that satisfy the `DefaultConstructible` requirements, using a value-initialized iterator as the source of a copy or move operation." – T.C. Sep 23 '15 at 21:19
  • 1
    This appears to be https://support.microsoft.com/en-us/kb/2545588 – T.C. Sep 23 '15 at 21:25
  • @T.C. Can you help me understand what is meant here by "singular value." The linked hot fix and your comment both use the term and I'm not sure what that means. That hot fix is very promising though. I'm gonna try it tomorrow morning. – Jonathan Mee Sep 24 '15 at 01:31
  • 1
    @JonathanMee A singular value is one that's not associated with any sequence. For instance, null or uninitialized pointers. – T.C. Sep 24 '15 at 01:38
  • @T.C. Wow, that hot fix is exactly what I need then. Your quote also makes my assignment seem terrifyingly illegal. – Jonathan Mee Sep 24 '15 at 02:50
  • @T.C. Wonderful! You are correct that that hotfix solved my issue. Could you put that in an answer that I can accept? Incidentally the page you linked is only the knowledge base article. A download link can be requested here: http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=2545588&kbln=en-us – Jonathan Mee Sep 24 '15 at 12:29

1 Answers1

1

This code has undefined behavior. [iterator.requirements.general]/p6:

Iterators can also have singular values that are not associated with any sequence. [ Example: After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. —end example ] Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that satisfy the DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation. [ Note: This guarantee is not offered for default initialization, although the distinction only matters for types with trivial default constructors such as pointers or aggregates holding pointers. —end note ] In these cases the singular value is overwritten the same way as any other value. Dereferenceable values are always non-singular.

uninitialized is singular, and its use doesn't fall within any of the exceptions listed in the paragraph.

However, given the snippets you post, I suspect that your code wouldn't work either even if you value-initialize uninitialized, which is a bug in Microsoft's implementation, and which they fixed in a later hotfix.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • Incidentally the page you linked is only the knowledge base article. A download link can be requested here: http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=2545588&kbln=en-us – Jonathan Mee Sep 28 '15 at 11:05