2

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

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

您在遗留代码中清理捕获目标的方法是什么?我认为我可以通过operator new私有化来修复第一部分:

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

我怎样才能在编译时使事情的捕获面同样难看?我不想仅仅导致它落入catch (...)领土。

4

5 回答 5

3

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

为了更完全地防止指针抛出,您实际上需要做更多的工作。

隐藏所有形式的 operator new - 请参见此处

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

class MyExceptionClass
{
private:
    MyExceptionClass* operator&();
}
于 2009-06-09T22:31:02.733 回答
2

If I understand you correctly, you want to turn a bad practice into a compilation error.

By making the exception type non-heap-allocatable, you've managed to make this illegal:

throw new MyExceptionClass();

Alas, the next part can't be done like you want it. There's no way to make the catch block illegal. Although, if you've made it illegal to heap-allocate MyExceptionClass, there's no need to worry about the catch blocks. It'll just be wasted space.

If you want to enforce not catching by a pointer, you want a lint-like tool. I'd recommend looking at EDoC++. It's a modified gcc compiler to check for proper exception usage.

于 2009-06-09T20:26:30.253 回答
1

听起来您希望能够将所有通过指针抛出的实例更改为按值抛出。你有一个可行的工具来防止指针抛出。但是,您正在寻找一种方法来防止在所有抛出都更改后被指针意外捕获。

据我所知,这不能由语言强制执行。但是我认为一个简单的 sed 脚本来查找实例/catch (.* \*/应该足够好......

于 2009-06-09T18:31:22.233 回答
0

我通常

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

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

于 2009-06-09T18:23:33.617 回答
0

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

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

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

于 2009-06-09T18:27:49.290 回答