22 votes

fuite de mémoire sous GCC (mais pas Clang), en jetant au milieu d'un C++14 initialiseur de liste pour le std::list<shared_ptr>

Considérons le programme suivant:

#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;
}

Compilé comme ceci:

[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 sortie est:

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

Notez que les destructeurs ne sont pas appelés. Valgrind correctement se plaint de la fuite ainsi.

Ce qui semble violer l'un des principaux objectifs de l' std::make_shared -- à savoir que si une autre expression dans la déclaration de jette, l'objet partagé est bien détruit parce qu'il est enveloppé par un entièrement construite pointeur partagé objet.

Clang est ce que je voudrais ici:

[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:~] $ 

Alors, est-ce un bug de GCC, ou dois-je fixer mon programme?

12voto

Steve Lorimer Points 2248

En tournant mon commentaire répondre à la question de sorte que vous pouvez marquer la question répondu.

Ce qui semble être un bug de gcc

Bug 66139 - destructor a pas appelé pour les membres de l'partiellement construit anonyme struct/tableau

Notez en particulier les deux derniers cas de test qui utilisent std::initializer_list pour illustrer le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X