2016-08-17 5 views
22

は、以下のようなプログラムを検討:メモリGCC下リーク(ただしクラン)STDのためのC++ 14初期化子リストの真ん中に投げる::リスト<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の主な目的の1つに違反していると思われます。つまり、ステートメント内の別の式がスローすると、共有オブジェクトは完全に構築された共有ポインタオブジェクトによってラップされるため、適切に破棄されます。

[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のバグである、または私は私のプログラムを修正する必要があります:

クランは、私がここに希望何でしょうか?

+16

[gcc bug](https://gcc.gnu.org/ml/gcc-bugs/2015-05/msg01091.html)のように見えます:* "部分的に構築された匿名の構造体/配列のメンバーに対してデストラクタが呼び出されていません"*。 –

答えて

12

私のコメントを答えに変えて、質問に答えてマークすることができます。

これはgccのバグ

Bug 66139になりそうだ - これは使用特定の最後の2つのテストケースでは、部分的に構築され、匿名の構造体/配列

注意のメンバーのために呼び出されていないデストラクタ問題を説明するためにstd::initializer_list

+0

部分オブジェクト(コンストラクタから例外がスローされた場合に作成されます)とは何か異なりますが、デストラクタは後で呼び出されません –

関連する問題