我需要像这样连接C++的异常抛出机制:
namespace __cxxabiv1
{
extern "C" void __cxa_throw(void* voidPointerToActualObject, std::type_info* stdTypeInfoOfActualObject, void (*destructor)(void *))
{
// If thrownException is a custom exception type or something deriving from it, poke a value into it.
}
}
If you're wondering "Why would you do that?"
我有一个抛出异常的简单例子,它是一个非常简单的类层次结构的一部分:
#include <stdexcept>
class Upper : public std::exception
{
public:
int pokeMe = 111111;
};
class Lower : public Upper {};
int main()
{
throw Lower();
}
#include <cxxabi.h>
namespace __cxxabiv1
{
extern "C" void __cxa_throw(void* voidPointerToActualObject, std::type_info* stdTypeInfoOfActualObject, void (*destructor)(void *))
{
// The point is to do the equivalent of this:
Lower* staticallyTypedPointerToActualObject = reinterpret_cast<Lower*>(voidPointerToActualObject);
auto thisWorks = dynamic_cast<Upper*>(staticallyTypedPointerToActualObject);
thisWorks->pokeMe = 222222;
// But we don't know the actual static type, so we can't get a statically typed pointer. We only have a void* and a type_info:
auto abiTypeInfoOfActualObject = dynamic_cast<const abi::__class_type_info*>(stdTypeInfoOfActualObject);
auto abiTypeInfoOfUpper = dynamic_cast<const abi::__class_type_info*>(&typeid(Upper));
Upper* thisDoesNotWork = reinterpret_cast<Upper*>(abi::__dynamic_cast(voidPointerToActualObject, abiTypeInfoOfActualObject, abiTypeInfoOfUpper, -1));
thisDoesNotWork->pokeMe = 333333;
// Elided for clarity: Call the original __cxa_throw function here
// Instead, suppress these warnings:
(void)destructor; // Unused parameter
while (1) { } // Return from non-returning function
}
}
我看不出为什么__dynamic_cast
不能向上转换,但是它返回nullptr
。
为什么?我怎么才能让它工作?
它似乎能够做的向下投刚刚好,顺便说一句:
auto abiTypeInfoOfActualObject = dynamic_cast<const abi::__class_type_info*>(&typeid(Upper)); // Plonking this here for testing
auto abiTypeInfoOfUpper = dynamic_cast<const abi::__class_type_info*>(&typeid(Lower)); // Casting to Lower instead of Upper
Lower* thisDoesNotWork = reinterpret_cast<Lower*>(abi::__dynamic_cast(voidPointerToActualObject, abiTypeInfoOfActualObject, abiTypeInfoOfUpper, -1));
1条答案
按热度按时间2wnc66cl1#
我找到了2004年的一段对话
ABI文档不要求__dynamic_cast执行派生到基类的转换。那些实际上可以由编译器静态执行的__dynamic_cast操作必须由编译器静态执行--运行时库不希望在这种情况下被调用。
这就回答了那个问题。
但谈话中幸运地提到:
是;保持器知道静态类型;它可以抛出该类型的指针。强制转换操作可以捕获它正在查找的指针类型,或者使用catch(...)使强制转换失败。
这给了我一个想法来尝试这个(简化版):
我简直不敢相信,但它真的有效!
编辑:免责声明:看起来这样,析构函数回调实际上被调用了两次,因为如果使用
std::string pokeMe
,字符串在我第二次调用oldThrowFunction时就被丢弃了,我将在接下来的几天里进行试验。