我最近的任务是找出我们代码的一部分中的内存泄漏。泄漏最终在一个特定object...and的析构函数中,我发现了一些非常奇怪的东西。一位前同事写道:
File::~File()
try
{
Clear();
}
catch (...)
{
Log("caught exception");
}file类继承自一些基类。我的第一个问题是:这是严格合法的C++吗?它在Visual Studio2008中编译,但我向一些朋友/同事展示了它,他们对它的工作感到相当震惊。
然而,它实际上并不能像预期的那样工作:这个对象继承的基类有一个析构函数,这个析构函数现在永远不会被调用(而不是将析构函数包装在一个常规的方法块中,将try / catch作为该方法的一部分)。
任何人都可以尝试解释为什么允许这样做,为什么基类析构函数没有被调用?这里的析构函数并没有抛出。
发布于 2011-05-10 23:53:40
这是一个函数try块,它是完全合法的。
例如,请参见here。
在函数try块中可以做的事情,而不能在函数中的普通try块中做的唯一一次是捕捉构造函数初始化器列表中的表达式抛出的异常(即使这样,您最终也必须抛出一些东西),但这不适用于这里。
这个GOTW #66特别有趣,尽管它更专注于构造函数。它包含了这样的“道德”:
因为析构函数永远不会发出异常,所以析构函数的
-try-block根本没有实际用途。
为了补充说明,所编写的代码将导致由于ISO/IEC 14882:200315.3 except.handle /16而捕获的任何异常被重新抛出:
如果控制到达构造函数或析构函数的function-try-block的处理程序的末尾,则重新抛出正在处理的异常。..。
然而,在析构函数的函数try块的处理程序中有一个无参数的return是合法的-它只在构造函数的函数try块中被禁止-这将抑制异常的重新抛出。因此,这两种方法中的任何一种都可以防止异常离开析构函数。
File::~File()
try
{
Clear();
}
catch (...)
{
Log("caught exception");
return;
}File::~File()
{
try
{
Clear();
}
catch (...)
{
Log("caught exception");
}
}https://stackoverflow.com/questions/5952837
复制相似问题