我们都知道抛出指向异常的指针很糟糕:
try
{
...
throw new MyExceptionClass();
}
catch (MyExceptionClass* e)
{
...
}
您在遗留代码中清除捕获目标的方法是什么?我认为我可以通过operator new
私有来修复第一部分:
class MyExceptionClass
{
public:
...
private:
void* operator new(size_t);
}
如何在编译时使捕获方面同样难看?我不想让它落入catch (...)
领域。
答案 0 :(得分:3)
除了静态分析工具或代码审查之外,除了指针之外,您无法阻止捕获。但是,如果你几乎不可能抛出MyExceptionClass
指针,那么catch(MyExceptionClass*)
块将是死代码。
为了更完全地防止通过指针投掷,你实际上需要做更多的工作。
隐藏所有形式的operator new - 见here。
隐藏运算符的地址 - 抛出先前分配的对象的地址会带来一些抛出堆分配对象的相同问题。
class MyExceptionClass
{
private:
MyExceptionClass* operator&();
}
答案 1 :(得分:2)
如果我理解正确,你想把一个不好的做法变成编译错误。
通过使异常类型为非堆可分配,您已设法使其成为非法:
throw new MyExceptionClass();
唉,下一部分不能像你想要的那样完成。没有办法让catch块非法。虽然,如果你认为堆分配MyExceptionClass是非法的,那么就不必担心catch块了。这只是浪费空间。
如果你想强制不用指针捕捉,你需要一个类似lint的工具。 我建议看一下EDoC++。它是一个修改过的gcc编译器,用于检查正确的异常使用情况。
答案 2 :(得分:1)
听起来你希望能够通过指针将所有throw实例更改为按值抛出。你有一个可行的kludge,以防止指针投掷。但是你正在寻找一种方法来防止一旦所有的投掷被改变而意外地被指针捕获。
据我所知,这种语言无法强制执行。但是,一个简单的sed脚本来查找/catch (.* \*/
的实例应该足够好了我会想......
答案 3 :(得分:0)
我通常
try { throw MyException(); } catch (const MyException& e) { }
不确定,我理解你的问题。
答案 4 :(得分:0)
就C ++语言规则而言,你不能禁止指向一个类型的指针,这使得捕获它们的指针完全合法(无论多么丑陋)。我会编写一个简单的工具来查找所有catch(T*)
块并只更改它们。
我会说私有operator new
可能不起作用,因为可能仍会调用全局新运算符。我建议用于强制破坏动态分配的遗留代码库将是更改MyExceptionClass
的构造函数的签名 - 或者在默认构造函数中添加静态断言并强制编译失败以便您可以确定实例化这些默认构造的MyExceptionClass
类型的位置。
我要采取的另一种方法是寻找“throw new
”条款,然后解决这些问题。