Pérdida de memoria bajo GCC(pero no Clang) cuando se lanza en medio de una lista de inicializadores de C++ 14 para std:: list<shared_ptr>
exception-handling c++14 (1)
Convertir mi comentario en una respuesta para que pueda marcar la pregunta como respondida.
Esto parece ser un error gcc
Error 66139 - destructor no llamado para miembros de estructura / array anónima parcialmente construida
Tenga en cuenta en particular los dos últimos casos de prueba que utilizan std::initializer_list
para ilustrar el problema.
Considere el siguiente programa:
#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;
}
Compilado de esta manera:
[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:~] $
La salida es:
[little:~] $ ./list_init
ctor 0x1294c30
ctor 0x1294c50
caught exception.
done.
[little:~] $
Observa que los destructores no son llamados. Valgrind se queja correctamente de la fuga también.
Esto parece violar uno de los propósitos clave de std::make_shared
, a saber, que si se lanza otra expresión en la declaración, el objeto compartido se destruye adecuadamente porque está envuelto por un objeto puntero compartido totalmente construido.
Clang hace lo que me gustaría aquí:
[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:~] $
Entonces, ¿esto es un error de GCC, o necesito arreglar mi programa?