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?
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 "*. –