我正在考虑在我正在编写的一些库中使用异常处理。该代码库最终可以在多个dlls中实现。我知道跨dlls使用异常处理不是一个好主意--然而,这样做安全吗?
class IDllSafeException
{
public:
virtual void AddRef() = 0;
virtual void Release() = 0;
virtual int GetErrorCode() const = 0;
virtual const char * What() const = 0;
};假设这是一种有效的方法,我真的希望通过值来捕获,而不是指针。这样,我就可以有一个自动调用Release()的包装类。
因此...
template <typename T>
class SafeExceptionT
{
public:
SafeExceptionT(T *);
SafeExceptionT(SafeExceptionT &);
SafeExceptionT & operator=(SafeExceptionT &);
~SafeExceptionT();
int GetErrorCode() const;
const char * What() const;
private:
T * m_pException;
};
typedef SafeExceptionT<IDllSafeException> SafeException;作为模板意味着所有catch块都将生成自己的布局,并在析构函数中调用can m_pException->Release() (复制发生时使用AddRef() )。我还可以根据需要实现不同类型的异常。
我的catch代码块看起来就像这样...
try
{
ThrowSomething();
}
catch(SafeException except)
{
const char * psz = except.What();
int nErrorCode = except.GetErrorCode();
}..。
void ThrowSomething()
{
// Concrete implementation omitted for brevity
throw new DllSafeException(1, "something went wrong");
}我本以为这会起作用,但是我的异常处理程序没有被捕获,即使我有一个非显式的SafeException构造函数。
然而,我似乎只能通过指针来捕获...
try
{
ThrowSomething();
}
catch(SafeException except)
{
/// IGNORED!
...
}
catch(IDllSafeException * pExcept)
{
// CAUGHT BY POINTER but we now have to micro-manage.
const char * psz = pExcept->What();
int nErrorCode = pExcept->GetErrorCode();
pExcept->Release();
}对于如何在异常处理程序中匹配类型,是否有特殊的规则?
发布于 2017-09-26 19:25:43
如果任何人感兴趣,上面的代码通过使用抽象基类和依赖于编译器之间一致的vtable布局,确实成功地绕过了dll边界异常问题。
我在VS2008和VS2017上进行了测试。我在每个环境中构建了一个dll,每个环境中都有一个控制台应用程序。dll引发异常,exception类在内部聚合一个对象,以确保发生堆分配。
我还在不同的dll/控制台应用程序之间混合和匹配了C-runtime的版本(静态和dll)。我可以成功地引发/捕获跨dll划分的异常。
不出所料,vtable布局确保了delete/~tor在正确的二进制文件中执行。
唯一需要注意的是,您必须通过抽象接口抛出。这也意味着确保您手动调用pEx->Release。我知道这不是很好,但我仍然不知道为什么我的另一个类不能通过它的非显式构造函数来捕获异常。
https://stackoverflow.com/questions/46413673
复制相似问题