3

Seeing a crash with the below code. I know initialize_lists have a poor reputation in VS, but I thought most of them were fixed with 2013 sp3. The same code works fine in g++ (6.1). Am I missing something here? This seems far too simple.

The debugger suggests a problem with an invalid iterator in the xstring module. The same code works find with integers, so I'm guessing it relates to some sort of string specific optimization.

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

int main(int argc, char** argv)
{
    std::vector<std::string> x = {"a","b","c","d"};

    for(auto i : x)
        std::cout << i << ":";
    std::cout << std::endl;

    x.insert(x.end(), {"e","f"});  // Crash here

    for(auto i : x)
        std::cout << i << ":";
    std::cout << std::endl;

    return 0;
}
R Gould
  • 33
  • 3
  • FWIW - in VC2013 RC4 if I add a try/catch around the `insert`, it catches `bad_alloc`. If I `insert` `{std::string("e"), "f")}` it works. – Tony Delroy May 06 '16 at 01:47

1 Answers1

0

You would be surprised if you try inserting 3 elements like x.insert(x.end(), {"e","f", "g"});. No crash, right!

This is a bug in MSVC 2013 and seems to be fixed in MSVC 2015. Here is an explanation to shed some light to where the problem occurs. If you try only declaring std::string a{ "a", "b" }; you will see that it compiles fine but it causes a crash. If you add one more element, then it won't compile at all. So, what happens with the insert is that it calls the string constructor instead of calling vector constructor.

Eissa N.
  • 1,695
  • 11
  • 18
  • You're right about 3 text values working, but for the two-value case I've added debug trace to all overloads of `insert` and don't see *any* overload being called. It seems to throw while preparing the parameters, which is crazy - trace in the `initializer_list<>` constructor's not even displayed. – Tony Delroy May 06 '16 at 03:01
  • Thanks. At least that confirms it's a compiler bug, if a bit of a weird one. Upgrading isn't an option just yet, will just have to avoid it. Seems I can work around by prefixing std::initializer_list{"e","f"}. – R Gould May 06 '16 at 04:36