简体   繁体   中英

“Invalid iterator range” while inserting initializer_list to an std::vector

This code compiles and runs fine as expected on Ideone :

#include <iostream>
#include <string>
#include <vector>

int main() {

    std::vector<std::wstring> strVec;
    strVec.insert(strVec.end(), { L"black", L"white", L"red" });
    strVec.insert(strVec.end(), { L"blue", L"green" }); // STL exception

    for (auto &i : strVec) {
        std::wcout << i << " ";
    }
    return 0;
}

However, fails with "invalid iterator range" in MSVC (Visual Studio 2013).. Any insight?

BTW, inserting more elements works, eg on the second insert, this works in MSVC:

strVec.insert( strVec.end(), { L"blue", L"green", L"yellow" } );

Related to capacity/size and invalidating some iterators? But second insert requests new iterator end() , which must be valid, right? Or... it's actually about initializer list?

Note: Not looking for workarounds here (tons of them) - just trying to figure out whether this is MSVC-specific bug or something legit wrong is going on...

VS 2013 has selected the overload vector<T>::insert(const_iterator, const T&) , constructing wstring from a pair of pointers const wchar*, const wchar* interpreted as the start and end of a range of characters; note that a wide string literal decays to a const wchar* pointer. This is why the problem only occurs when you try to insert precisely 2 elements.

Here's the call stack:

msvcp120d.dll!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
Project1.exe!std::_Debug_range2<wchar_t const *>(const wchar_t * _First, const wchar_t * _Last, const wchar_t * _File, unsigned int _Line, std::random_access_iterator_tag __formal) Line 576   C++
Project1.exe!std::_Debug_range<wchar_t const *>(const wchar_t * _First, const wchar_t * _Last, const wchar_t * _File, unsigned int _Line) Line 584  C++
Project1.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >(const wchar_t * _First, const wchar_t * _Last) Line 860    C++
Project1.exe!main() Line 9  C++

VS 2013 is erroneous, because [over.ics.rank] :

3 - [...]

  • List-initialization sequence L1 is a better conversion sequence than list-initialization sequence L2 if:
    • L1 converts to std::initializer_list<X> for some X and L2 does not [...]

This is fixed in VS2015.

Possibly this happens because when you write { L"blue", L"green" } compiler use them as two pointers to construct value ( std::wstring ) and pass it into next std::vector::insert overloading:

insert( const_iterator pos, const T& value ); 

So it's likely that running from pointer L"blue" to L"green" ends somewhere where program has no permission to read, or it's check that first pointer is less than second and throw exception when they not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM