【问题标题】:Pointer-to-Exception Clean-Up指向异常清理的指针
【发布时间】:2010-11-01 13:58:35
【问题描述】:

我们都知道抛出异常指针是不好的:

try
{
    ...
    throw new MyExceptionClass();
}
catch (MyExceptionClass* e)
{
    ...
}

您用什么方法清理遗留代码中的 catch 目标?我认为我可以通过将operator new 设为私有来修复第一部分:

class MyExceptionClass
{
public:
    ...
private:
    void* operator new(size_t);
}

我怎样才能在编译时使事情的捕获面同样丑陋?我不想只是让它落入catch (...) 领域。

【问题讨论】:

  • 您允许更改多少代码/are/?理想情况下,您将更改抛出代码和捕获代码,并完成它。但当然,事情可能没有那么简单。
  • 这部分是为了找到我们进行更改的地方;当我们开始着手处理这个问题时,我们可以 100% 控制我们可以更改哪些代码。

标签: c++ exception legacy


【解决方案1】:

除了静态分析工具或代码审查之外,您无法采取任何措施来防止指针捕获。但是,如果您几乎不可能抛出 MyExceptionClass 指针,则 catch(MyExceptionClass*) 块将是死代码。

为了更彻底地防止指针抛出,你实际上需要做更多的工作。

隐藏所有形式的 operator new --here

隐藏地址操作符 -- 抛出先前分配的对象的地址会带来一些与抛出堆分配对象相同的问题。

class MyExceptionClass
{
private:
    MyExceptionClass* operator&();
}

【讨论】:

  • 好点;我没有想到地址操作符。
【解决方案2】:

如果我对你的理解正确,你想把一个不好的做法变成一个编译错误。

通过将异常类型设置为不可堆分配,您已设法使其非法:

throw new MyExceptionClass();

唉,下一部分不能如你所愿。没有办法使 catch 块非法。虽然,如果您将堆分配 MyExceptionClass 设为非法,则无需担心 catch 块。这只会浪费空间。

如果您想强制不通过指针捕获,您需要一个类似 lint 的工具。 我建议查看EDoC++。这是一个经过修改的 gcc 编译器,用于检查是否正确使用异常。

【讨论】:

    【解决方案3】:

    听起来您希望能够将 throw by pointer 的所有实例更改为 throw by value。你有一个可行的组合来防止指针抛出。但是您正在寻找一种方法,以防止在所有抛出都更改后被指针意外捕获。

    据我所知,语言无法强制执行此操作。但是我认为一个简单的 sed 脚本来查找 /catch (.* \*/ 的实例应该已经足够好了......

    【讨论】:

    • 是的。我担心会是这样。谢谢。
    【解决方案4】:

    就 C++ 语言规则而言,您不能禁止指向使捕获指向它们的指针完全合法的类型的指针(无论多么丑陋)。我会编写一个简单的工具来查找所有 catch(T*) 块并更改它们。

    我会说将 operator new 设为私有可能不起作用,因为可能仍会调用全局 new 运算符。我建议遗留代码库强制破坏动态分配是更改 MyExceptionClass 的构造函数的签名 - 或在默认构造函数中添加静态断言并强制编译失败,以便您可以确定在哪里这些默认构造的MyExceptionClass 类型被实例化。

    我会采取的另一种方法是查找“throw new”子句并修复它们。

    【讨论】:

      【解决方案5】:

      我经常

      尝试 { 抛出我的异常(); } catch (const MyException& e) { }

      不确定,不过,我理解你的问题是否正确。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-08
        • 2020-10-23
        • 2013-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多