C++编译器如何实现异常处理
st(my_hdlr) - (reinterpret_cast(cpp_hdlr) + 5); if(!saved_handler_instructions) { if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, sizeof(cpp_handler_instructions))) return false; saved_handler_instructions = true; } return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr)); } bool restore_cpp_handler() { if(!saved_handler_instructions) return false; else { void* loc = __CxxFrameHandler; return WriteMemory(loc, cpp_handler_instructions, sizeof(cpp_handler_instructions)); } } } 编译指令#pragma pack(push, 1)告诉编译器不要在jmp_instr结构中填充任何用于对齐的空间。没有这条指令,jmp_instr的大小将是8字节,而我们需要它是5字节。 现在重新回到异常处理这个主题上来。调用catch块时,它可能重新抛出异常或抛出新异常。前一种情况下,异常处理程序必须继续传播(propagate)当前异常;后一种情况下,它需要在继续之前销毁原来的异常。此时,处理程序要面对两个难题:“如何知道异常是源于catch块还是程序的其他部分”和“如何跟踪原来的异常”。我的解决方法是:在调用catch块之前,把当前异常保存在exception_storage对象中,并注册一个专用于catch块的异常处理程序——catch_block_protector。调用get_exception_storage()函数,就能得到exception_storage对象: exception_storage* p = get_exception_storage(); p->set(pexc, pexc_info); 注册 catch_block_protector; 调用catch块; //.... 这样,当catch块(重新)抛出异常时,程序将会执行catch_block_protector。如果是抛出了新异常,这个函数可以从exception_storage对象中分离出前一个异常并销毁它;如果是重新抛出原来的异常(可以通过ExceptionInformation数组的前两个元素知道是新异常还是旧异常,后一种情况下着两个元素都是0,参见下面的代码),就通过拷贝ExceptionInformation数组来继续传播它。下面的代码就是catch_block_protector()函数的实现。 //------------------------------------------------------------------- |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |