Try/Catch块替换析构函数中的方法块

phy*_*ler 6 c++ visual-studio-2008

我最近的任务是在代码的一部分中查找内存泄漏.泄漏最终出现在特定对象的析构函数中......我发现了一些非常奇怪的东西.一位前同事写道:

File::~File()
try
{
    Clear();
}
catch (...)
{
    Log("caught exception");
}
Run Code Online (Sandbox Code Playgroud)

文件类继承自一些基类.我的第一个问题是:这是严格合法的C++吗?它在Visual Studio 2008中编译,但我向几个朋友/同事展示了它们,并且它们相当惊恐,它的工作原理.

但它实际上并没有按预期工作:这个对象继承的基类有一个现在永远不会被调用的析构函数(而不是如果你只是将析构函数包装在常规方法块中,将try/catch作为一部分)那个方法).

任何人都可以尝试解释为什么允许这样做,以及为什么没有调用基类析构函数?这里的析构函数并没有抛出.

CB *_*ley 10

这是一个功能尝试块,它是完全合法的.

例如,请参见此处.

你可以在一个函数中执行某些操作的唯一一次你在一个函数中的普通try块中无法做的事情就是捕获构造函数初始化列表中表达式抛出的异常(甚至你最终还是要抛出一些东西) ,但这不适用于此.

GOTW#66是特别有趣的,尽管它集中更多的构造函数.它包含这个"道德":

由于析构函数永远不会发出异常,因此析构函数try-try-blocks根本没有实际用途.

只是为了补充说明,编写的代码将导致由于ISO/IEC 14882:2003 15.3 [except.handle]/16而被捕获的任何异常:

如果控制到达构造函数或析构函数的function-try-block的处理程序的末尾,则重新抛出正在处理的异常.[...]

但是,return在函数try块的处理程序中为析构函数设置无参数是合法的- 它只在构造函数的函数try块中被禁止 - 这将抑制异常的重新抛出.因此,这些替代方案中的任何一个都可以防止异常离开析构函数.

File::~File()
try
{
    Clear();
}
catch (...)
{
    Log("caught exception");
    return;
}
Run Code Online (Sandbox Code Playgroud)
File::~File()
{
    try
    {
        Clear();
    }
    catch (...)
    {
        Log("caught exception");
    }
}
Run Code Online (Sandbox Code Playgroud)