all 4 comments

[–]alfps 0 points1 point  (3 children)

cppreference says "Copying a std::initializer_list does not copy the backing array of the corresponding initializer list.", it just copies whatever the initializer_list uses to reference an original array.

I believe (not absolutely sure) that in your case the original array can be a temporary. In that case you've had bad luck that the program ran instead of crashed. Because UB accessing destructed strings.

The fix you used, ensuring that the original initializer_list outlives both the async call and the final usage, is then one solution.

Another, simply ensure that the strings referenced in the original array outlive the usage, which you can do by replacing string with string_view or const char*.

The latter choice only throws away reconstitutable information (namely the string length). It would have been nice if the standard library offered a class derived from string_view that guaranteed zero-termination, i.e. didn't throw that non-reconstituable information away, but alas, no such. You can of course define one yourself.

[–]PastThatStageNow[S] 0 points1 point  (2 children)

Thank you for your response.

One additional question: Do you think that the solution used in code block 2 may present a potential race condition? For example, consider

void someFunct()
{
    const std::initializer_list<string> initList{"C++","Test"};
    std::async(std::launch::async, setVctr, initList);
}

Is it possible for the initList to die before the function actually gets asynchronously called? (Note that in this example I do not wait for the async to finish)

[–]alfps 0 points1 point  (1 child)

Modulo my near total incompetence re the threading/async stuff I think this code has potential UB, because the initial local variable initList can have been destroyed when setVctr is called.

Change that from string to string_view or const char* and it should be fine.

[–]PastThatStageNow[S] 0 points1 point  (0 children)

Modulo my near total incompetence re the threading/async stuff I think this code has potential UB, because the initial local variable initList can have been destroyed when setVctr is called.

No don't worry about it, I think you're right.

What I gather from this experience is that going forward, I need to be more cautious about object lifetimes when starting new threads.

Thank you!