最近,我受命在代码的一部分中查找内存泄漏。泄漏最终发生在特定对象的析构函数中……我发现了一些非常奇怪的东西。一位前同事写道:

File::~File()
try
{
    Clear();
}
catch (...)
{
    Log("caught exception");
}

文件类继承自一些基类。我的第一个问题是:这是严格合法的C++吗?它可以在Visual Studio 2008中编译,但是我向几个 friend /同事展示了它,他们对此工作感到非常恐惧。

但是,它实际上并没有按预期的方式工作:该对象所继承的基类具有一个现在从未被调用的析构函数(与如果您仅将析构函数包装在常规方法块中,而将try/catch作为一部分该方法)。

谁能解释一下为什么允许这样做以及为什么不调用基类析构函数?这里的破坏者没有抛出。

最佳答案

这是一个功能try块,完全合法。

参见,例如here

在函数try块中只能在函数的普通try块中无法执行的操作的唯一时间是捕获构造函数初始化器列表中的表达式引发的异常(即使那样,最终您也必须抛出一些东西) ,但这不适用于这里。

这个GOTW #66特别有趣,尽管它更多地集中在构造函数上。它包含以下“道德”:



只是为了澄清起见,编写的代码将导致由于ISO/IEC 14882:2003 15.3 [except.handle]/16:而捕获的任何异常被重新抛出。



但是,在析构函数的函数try块的处理程序中具有无参数return是合法的-仅在构造函数的函数try块中禁止使用ojit_code-这将阻止异常的重新抛出。因此,这些替代方案中的任何一种都可以防止异常离开析构函数。

File::~File()
try
{
    Clear();
}
catch (...)
{
    Log("caught exception");
    return;
}
File::~File()
{
    try
    {
        Clear();
    }
    catch (...)
    {
        Log("caught exception");
    }
}

关于c++ - Try/Catch块代替析构函数中的方法块,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5952837/

10-13 07:31
查看更多