【发布时间】:2015-07-24 05:09:56
【问题描述】:
在以下代码中:
#include <memory>
#include <iostream>
void mydeallocator(int * x) {
std::cerr << "Freeing memory" << std::endl;
delete x;
}
struct Foo {
std::unique_ptr <int,std::function <void(int*)>> x;
Foo(bool fail) : x(new int(1),mydeallocator) {
if(fail)
throw std::runtime_error("We fail here");
}
};
int main() {
{auto foo1 = Foo(false);}
{auto foo2 = Foo(true);}
}
调用Foo(true) 时似乎没有正确释放内存。也就是说,当我们编译并运行这个程序时,我们得到了结果:
Freeing memory
terminate called after throwing an instance of 'std::runtime_error'
what(): We fail here
Aborted
我认为应该调用两次消息Freeing memory。基本上,根据question 和 ISO C++ 人员here 和here,我的理解是堆栈应该在Foo 的构造函数上展开,并且x 应该调用它的析构函数,它应该调用@ 987654330@。当然,这并没有发生,那为什么内存没有被释放呢?
【问题讨论】:
-
@TheParamagneticCroissant Foo 的构造函数抛出异常,而不是
unique_ptr的构造函数。由于在抛出异常时x已完全构造,因此应为x调用unique_ptr的析构函数。 -
@TheParamagneticCroissant
~Foo()不会运行,但~unique_ptr()应该 - 不? -
不仅如此,因为你没有捕捉到异常,你会因为程序中止而丢失控制台输出?
-
哦,等等,你
throw;没有一个活跃的例外。那直接到terminate。根本不会发生堆栈展开。 -
你没有捕捉到异常,所以在释放 unique_ptr 之前执行到
terminate()。如果添加catch处理程序,您将看到两条消息。