Is it unsafe to use a copied list of initializers in a range based loop?

This is very similar to the question I asked earlier today . However, the example I gave in this question is incorrect; by mistake, I was looking for the wrong source file, and not the one that actually had the error that I described. Anyway, here is an example of my problem:

struct base { };
struct child1 : base { };
struct child2 : base { };

child1 *c1;
child2 *c2;

// Goal: iterate over a few derived class pointers using a range-based for loop.
// initializer_lists are convenient for this, but we can't just use { c1, c2 }
// here because the compiler can't deduce what the type of the initializer_list
// should be. Therefore, we have to explicitly spell out that we want to iterate
// over pointers to the base class.
for (auto ptr : std::initializer_list<base *>({ c1, c2 }))
{
   // do something
}

It was the site of some subtle memory corruption errors in my application. After several experiments, I found that changing the above value caused the failures that I observed to disappear:

for (auto ptr : std::initializer_list<base *>{ c1, c2 })
{
   // do something
}

, . ; , , - , std::initializer_list copy? , , , .

, , std::initializer_list<base *>, ?

: , , :

#include <initializer_list>
#include <memory>

struct Test
{
    int x;
};

int main()
{
    std::unique_ptr<Test> a(new Test);
    std::unique_ptr<Test> b(new Test);
    std::unique_ptr<Test> c(new Test);
    int id = 0;
    for(auto t : std::initializer_list<Test*>({a.get(), b.get(), c.get()}))
        t->x = id++;
    return 0;
}

macOS Apple LLVM 8.1.0 (clang-802.0.42), :

clang++ -O3 -std=c++11 -o crash crash.cc

segfault . clang (8.0.0) . , gcc Linux .

, undefined - , ( , clang ), clang.

2: . , mainline clang v3.8.1 v3.9.0. v3.9 int main() { return 0; }, , . operator new, t->x , . , .

+4

Source: https://habr.com/ru/post/1675666/


All Articles