2016-08-17 16 views
22

Hãy xem xét các chương trình sau đây:bộ nhớ bị rò rỉ thuộc GCC (nhưng không Clang) khi ném ở giữa C++ 14 danh sách initializer cho std :: danh sách <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; 
} 

Biên soạn như thế này:

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

Đầu ra là:

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

Chú ý rằng hàm hủy không được gọi. Valgrind chính xác phàn nàn về sự rò rỉ là tốt.

Điều này dường như vi phạm một trong những mục đích chính của std::make_shared - cụ thể là nếu một biểu thức khác trong câu lệnh ném, đối tượng được chia sẻ sẽ bị phá hủy đúng cách vì nó được bao bọc bởi đối tượng được chia sẻ hoàn toàn.

Clang làm những gì tôi muốn ở đây:

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

Vì vậy, đây là một lỗi GCC, hay tôi cần phải sửa chữa chương trình của tôi?

+16

Trông giống như [lỗi gcc] (https://gcc.gnu.org/ml/gcc-bugs/2015-05/msg01091.html): * "destructor không được gọi cho các thành viên của cấu trúc/mảng ẩn danh được cấu trúc một phần "*. –

Trả lời

12

Biến nhận xét của tôi thành câu trả lời để bạn có thể đánh dấu câu hỏi là đã trả lời.

này có vẻ là một lỗi gcc

Bug 66139 - destructor không kêu gọi các thành viên của xây dựng phần struct vô danh/mảng

Lưu ý đặc biệt là hai trường hợp thử nghiệm cuối cùng mà sử dụng std::initializer_list để minh họa sự cố.

+0

Có gì khác với các đối tượng một phần (được tạo ra nếu ngoại lệ được ném từ hàm tạo) và hàm hủy sẽ không được gọi sau –

Các vấn đề liên quan