Подтвердить что ты не робот

Утечка памяти под GCC (но не Clang) при метании в середине списка инициализаторов С++ 14 для std:: list <shared_ptr>

Рассмотрим следующую программу:

#include <stdexcept>
#include <stdio.h>
#include <memory>
#include <list>
class Foo {
public:
    Foo(){
        if (s_ct==0) {throw std::bad_alloc();}
        --s_ct;
        fprintf(stderr, "ctor %p\n", this);
    }
    ~Foo(){
        fprintf(stderr, "dtor %p\n", this);
    }
private:
    static int s_ct;
};

int Foo::s_ct = 2;

int main(){
    try {
        std::list<std::shared_ptr<Foo>> l = {
            std::make_shared<Foo>(),
            std::make_shared<Foo>(),
            std::make_shared<Foo>()
        };
    } catch (std::bad_alloc&) {
        fprintf(stderr, "caught exception.\n");
    }
    fprintf(stderr, "done.\n");
    return 0;
}

Скомпилировано следующим образом:

[little:~] $ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR     PURPOSE.

[little:~] $ g++ --std=c++14 -o list_init list_init.cc
[little:~] $ 

Вывод:

[little:~] $ ./list_init 
ctor 0x1294c30
ctor 0x1294c50
caught exception.
done.
[little:~] $ 

Обратите внимание, что деструкторы не вызываются. Valgrind правильно также жалуется на утечку.

Это, по-видимому, нарушает одну из ключевых целей std::make_shared - а именно, что если вызывается другое выражение в выражении, общий объект получает должным образом уничтоженный, потому что он обернут полностью созданным объектом общего указателя.

Clang делает то, что я хотел бы здесь:

[little:~] $ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
[little:~] $ clang++ --std=c++14 -o foo list_init.cc
[little:~] $ ./foo
ctor 0x1dfec30
ctor 0x1dfec50
dtor 0x1dfec50
dtor 0x1dfec30
caught exception.
done.
[little:~] $ 

Так это ошибка GCC, или мне нужно исправить мою программу?

4b9b3361

Ответ 1

Превращение моего комментария в ответ, чтобы вы могли отметить вопрос как ответ.

Это выглядит как ошибка gcc

Ошибка 66139 - деструктор не вызван для членов частично построенной анонимной структуры/массива

Обратите внимание, в частности, на последние два тестовых примера, которые используют std::initializer_list для иллюстрации проблемы.