fbpx
维基百科

结构化异常处理

结构化异常处理,是Windows操作系统上,Microsoft对C/C++程序语言做的语法扩展,用于处理异常事件的程序控制结构。

异常事件是打断程序正常执行流程的不在期望之中的硬件、软件事件。硬件异常是CPU抛出的如“除0”、数值溢出等;软件异常是操作系统与程序通过RaiseException语句抛出的异常。

Microsoft扩展了C语言的语法,用 try-except与try-finally语句来处理异常。[1]异常处理程序可以释放已经获取的资源、显示出错信息与程序内部状态供调试、从错误中恢复、尝试重新执行出错的代码或者关闭程序等等。

一个__try语句不能既有__except,又有__finally。但try-except与try-finally语句可以嵌套使用。

try-except

__try  {  // 受保护执行的代码 } __except ( 过滤表达式 ) {  // 异常处理代码 } 

首先,__try复合语句中的受保护的代码被执行。如果没有异常发生,则继续执行__except复合语句之后的代码。如果__try复合语句中的受保护执行的代码发生了异常,或受保护执行的代码调用的函数内部发生了异常并要求调用者来处理该异常,__except语句的过滤表达式(filter expression)被求值,根据其结果来决定如何处理异常:

  • EXCEPTION_CONTINUE_EXECUTION (–1)  : 导致异常的问题已经解决,在异常出现的现场重新执行操作。
  • EXCEPTION_CONTINUE_SEARCH (0) :当前__except语句不能处理该异常,通知操作系统继续搜寻该线程其他的异常处理程序。
  • EXCEPTION_EXECUTE_HANDLER (1):当前__except语句识别该异常,通过执行__except的复合语句来处理该异常。然后执行__except复合语句之后的代码。

内在函数GetExceptionCode返回一个32位整型值,表示异常的类型。内在函数GetExceptionInformation返回异常的详细信息及现场信息(如CPU寄存器的值) 。这两个函数可用于异常表达式中来判断是否处理该异常。这里说的内在函数(intrinsic function),是指编译器提供内联(inline)实现的函数。

Windows操作系统的应用程序的main()函数受到结构化异常的try-except语句保护,因此程序的未被处理的异常都会被捕获。这是因为,Windows操作系统在加载用户进程时,Kernel32.dll中的BaseProcessStart函数在__try块中调用了用户进程的入口函数mainCRTStartup,因此用户程序的所有异常都会被捕获、得到处理。

可以使用C++运行时库中的_set_se_translator()函数把结构化异常转为抛出一个C++对象的C++异常。此外,C++异常的catch(...)语句也能直接捕捉结构化异常。

可以使用操作系统运行时库kernel32中的SetUnhandledExceptionFilter()函数设置顶层未处理异常过滤器(top-level unhandled exception filter),捕获进程的各个线程中一切未被处理的结构化异常。该函数一般用于从特定的错误中恢复,如无效的调用栈(invalid stack)。

try-finally语句

__try {  // 受保护执行的代码  } __finally {  // 清理用途的代码 } 

__try复合语句中受保护的代码以任何方式执行结束后,不论__try复合语句是因为出现异常而非正常结束,还是没有出现异常而正常结束,__finally复合语句中的代码都会被执行。

如果__try复合语句中受保护的代码的执行没有出现异常,包括用goto语句或longjump系统函数跳出__try复合语句等情形,这时将执行__finally复合语句,然后执行try-finally语句之后的其他代码。

在__finally复合语句中使用内在函数AbnormalTermination判断是正常结束还是非正常结束__try复合语句。

执行顺序

如果__try复合语句中受保护的代码执行中出现了异常,首先按函数调用顺序从新向旧搜索所有包含了出现异常的执行点的try-except语句,执行每个except的过滤函数,直到某个try-except语句的过滤函数结果值为EXCEPTION_EXECUTE_HANDLER。这时,再从包含异常出现的执行点的最内层try-finally语句开始由内向外执行每个finally块中的代码,直至回退到那个过滤函数结果值为EXCEPTION_EXECUTE_HANDLER的try-except语句执行其except块,最后执行该try-except语句后面的其他代码。

__leave关键字用在 try-finally 语句的受保护节(try块)中,其效果是跳转到受保护节的结尾处。 与goto语句跳出受保护节不同,__leave语句更为有效,因为它不会导致堆栈展开。

例子

  #include <stdio.h> #include <windows.h> // for EXCEPTION_ACCESS_VIOLATION #include <excpt.h> int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)  {  printf("在異常表達式中\n");  if (code == EXCEPTION_ACCESS_VIOLATION) {  printf("接受處理訪問違例異常\n");  return EXCEPTION_EXECUTE_HANDLER;  }  else {  printf("其他異常都不處理\n");  return EXCEPTION_CONTINUE_SEARCH;  }; } int main() {  int* p = 0x00000000; // pointer to NULL  printf("開始主程序\n");  __try{  printf("進入外層的try\n");  __try{  printf("進入內層的try\n");  int *p=0; // 空指針  *p = 13; // 導致訪問衝突異常  }__finally{  printf("在finally內部。");  printf(AbnormalTermination() ? "非正常終止\n" : "正常終止\n");  }  }__except(filter(GetExceptionCode(), GetExceptionInformation())){  printf("在except內部\n");  }  printf("主函數結束\n"); } 

輸出結果為:

開始主程序 進入外層的try 進入內層的try 在異常表達式中 接受處理訪問違例異常 在finally內部。非正常終止 在except內部 主函數結束 

与Windows异常处理机制的关系

Windows操作系统(自Windows95起),对每个用户线程,都设立一个异常处理帧链表来处理异常事件。该链表的每个异常处理帧由两个成员组成,分别是链表上一项地址、当前异常处理器地址,组成了结构_EXCEPTION_REGISTRATION_RECORD。异常处理器是指一个处理异常的回调函数(callback function)。线程信息块(thread information block)的开始处(即FS:[0]指向的内存,FS是CPU的一个段寄存器)保存了异常处理帧链表的表头项的地址。程序执行遇到异常事件而中断时,操作系统的RtlDispatchException函数会从FS:[0]指向的链表表头依次调用每个节点包含异常处理回调函数,直到某个异常处理回调函数的返回值为0表示已经处理该异常,该线程可以恢复执行。链表最末一项是操作系统在装入线程时设置的指向kernel32!UnhandledExceptionFilter函数,该函数总是向用户显示“Application error”对话框。

上述异常处理器程序及链表,是由用户程序自己安装的。链表各节点保存在程序调用栈(call stack)上。

Windows异常处理机制支持嵌套异常的处理,即在执行异常处理回调函数时再次发生异常。这种情况下仍遵照普通异常处理机制,操作系统RtlDispatchException函数再入处理新出现的嵌套的异常。嵌套的异常的处理函数得到的DispatcherContext参数值即为在执行时发生了新异常的异常帧的地址。

各种编程语言基于上述Windows异常处理机制,设计了各自的异常处理语句控制结构。Microsoft扩展了C语言语法,设计了结构化异常处理的try-except与try-finally语句。一个函数的所有在函数的的try-except与try-finally形成了一个基于包含(enclosing)关系的森林 (数据结构)。一个函数内如果有__try语句,则在函数的入口与结尾处,编译器插入了EH_prolog与EH_epilog代码,把函数内所有在try块中被保护的代码包了起来。 EH_prolog在调用栈上创建一个_EXCEPTION_REGISTRATION_RECORD,作为异常处理链表的新的表头,其中包含了Visual C++ 的运行时库msvcrt.dll的__except_handler4函数地址。在函数块的结尾处,EH_epilog把这项_EXCEPTION_REGISTRATION_RECORD从链表头移除,恢复其原来的表头。__except语句中的过滤表达式,由挂在链表中的异常处理回调函数MSVCR100D!__except_handler4来调用执行,返回值即为过滤表达式的求值结果。

实际上,编译器实现结构化异常时,把链表每项的数据结构由2个成员扩展为5个成员,即在高地址方向追加了一个scopetable_entries类型结构体数组的指针、一个整型项表示执行点位于当前函数的哪个try块中、一个保存寄存器EBP的整数项。此后(低地址方向)紧接着是一个指向EXCEPTION_POINTERS结构的指针(前述的内在函数GetExceptionInformation即返回这个指针值)。

异常发生时,操作系统的异常处理机制的ntdll!RtlDispatchException函数会从FS:[0]指向的链表表头依次调用异常帧链表的每个节点所包含的异常处理回调函数MSVCR100D!__except_handler4,根据该回调函数的返回值来确定异常是否已经被处理,可以根据异常上下文(Exception context)恢复线程的执行。__except_handler4回调函数实际上只是调用了MSVCR100D!__except_handler4_common函数。__except_handler4_common函数是实际的workhorse,负责在当前异常帧所在的函数中查找那个try-except语句能够处理该异常(即过滤表达式的结果为1) 。[2]如果不存在这样的try-except块,__except_handler4_common函数返回ExceptionContinueExecution(值0),由RtlDispatchException继续访问异常帧链表的下一个节点。如果找到了能处理当前异常的try-except块,__except_handler4_common函数首先调用全局展开函数_EH4_GlobalUnwind,把从异常帧链表表头所在的函数,直到能处理当前异常的函数的下一层函数,都做栈展开(unwinding);然后,对能处理当前异常的函数,从包含执行点的最内存__try语句,直到能处理异常的try-except块,调用局部展开函数_EH4_LocalUnwind;再执行能处理异常的try-except块的异常处理代码;最后,继续执行try-except之后的其他代码。

全局展开,是由_EH4_GlobalUnwind调用ntdll!RtlUnwind,RtlUnwind遍历访问异常帧链表,把从表头帧到目标帧(不含)的所有异常处理回调函数用异常码(STATUS_UNWIND 即0C0000027H)、异常标志(EXCEPTION_UNWINDING即值2)调用。异常处理回调函数根据当前的异常码与异常标志,对当前异常帧所在函数,从包含了产生异常的执行点的最内层__try语句开始,直至函数内的最外层try块,依次调用try-finally的清理用途代码。这一步实际上是调用_EH4_LocalUnwind函数来完成。

局部展开,由_EH4_LocalUnwind函数实现,是从包含了产生异常的执行点的最内层__try语句开始,按着代码的包含关系向外直至目标try-except语句为止,依次调用try-finally的清理用途代码。

SAFESEH

为了防止篡改异常处理函数的地址,自Windows XP SP2起引入了检查异常处理函数的地址是否有效。但这仅用于x86。而x64或ARM已经把所有异常处理函数放在了PDATA节中;该节叫做“.pdata”或者Exception Directory,用于存放处理异常的信息。[3]

链接器选项/SAFESEH[:NO]用于设置是否需要开启。

如果/SAFESEH被使用,链接器生成的可执行映像文件(image)包含它的安全的异常处理函数的清单。

如果/SAFESEH未使用,链接器将检查如果所有的模块都兼容于安全的异常处理函数特性,则生成的可执行映像文件(image)包含它的安全的异常处理函数的清单;如果有模块不兼容于安全的异常处理函数特性,则生成的可执行映像文件(image)不包含安全的异常处理函数的清单。

如果/SAFESEH:NO被使用,链接器生成的可执行映像文件(image)不包含安全的异常处理函数的清单。

相关的Windows API函数

函数 描述
ExRaiseStatus 用指定状态代码触发异常
ExRaiseAccessViolation 触发STATUS_ACCESS_VIOLATION异常
ExRaiseDatatypeMisalignment 触发STATUS_DATATYPE_MISALIGNMENT异常

Visual C++编译选项

Visual C++编译器的编译选项/EH设置异常处理模型 (Exception Handling Model):

  • a 捕捉异步(asynchronous或structured)与同步(synchronous或C++)异常;C++的catch(...)语句也可捕捉异步异常。不论同步异常还是异步异常,所有局部变量对象都被自动析构。 /clr隐式包含了/EHa 。
  • s 只捕捉同步(synchronous或C++)异常,并假定使用extern "C" 声明的函数可能抛出异常。 C++的catch(...)语句不捕捉异步异常。异步异常不会导致C++局部对象被自动析构。
  • c
    • 对于/EHsc, 只捕捉同步(synchronous或C++)异常,并假定使用extern "C" 声明的函数不会抛出C++异常。
    • 对于/EHca, 等价于/EHa.
  • r 编译器对所有noexcept函数总是产生运行时终止检查代码。
  • 如果未指定/EH,则编译器将同时捕获异步结构化异常和 C++ 异常,但不会销毁由于异步异常超出范围的 C++ 对象。

参考文献

  1. ^ Microsoft Corp. Structured Exception Handling Functions. MSDN Library. 11/12/2009 [2009-11-17]. (原始内容于2010-03-06). 
  2. ^ 《Microsoft Journal》上的__except_handler3函数的伪代码. [2013-07-01]. (原始内容于2012-12-14). 
  3. ^ MSDN:/SAFESEH (Image has Safe Exception Handlers). [2017-02-14]. (原始内容于2017-02-14). 

外部链接

  • Igor Skochinsky. . OpenRCE. Monday, March 6, 2006 12:02.38 CST [2009-11-17]. (原始内容存档于2010-04-16). 
  • Microsoft Corp. Structured Exception Handling. MSDN Library. 2009-11-12 [2009-11-17]. (原始内容于2009-12-08). 
  • Matt Pietrek. . MSJ. Jan 1997, 12 (1) [2013-06-30]. (原始内容存档于2015-09-29).  Note that the examples given there do not work as-is on modern Windows systems (post XP SP2) due to the changes Microsoft made to address the security issues present in the early SEH design. The examples still work on later versions of Windows if compiled with /link /safeseh:no.
  • . Yasm manual. [2017-02-14]. (原始内容存档于2017-01-07). 
  • US patent 7,480,919 - Safe exceptions
  • Johannes Passing. . May 20, 2008 [2017-02-14]. (原始内容存档于2017-02-15).  Covers the obscure details needed to get low-level SEH (and particularly SafeSEH) code to work on more modern Windows.
  • Igor Skochinsky. . OpenRCE. Monday, March 6, 2006 12:02.38 CST [2009-11-17]. (原始内容存档于2010-04-16). 
  • Matt Miller. . Technet. 2 Feb 2009 [2017-02-14]. (原始内容存档于2014-07-01). 
  • Stéfan Le Berre, Damien Cauquil. (PDF). Sysdream. 22 Dec 2009. (原始内容 (PDF)存档于2012-09-07). 
  • Joshua J. Drake. Old Meets New: Microsoft Windows SafeSEH Incompatibility. 10 Jan 2012 [2017-02-14]. (原始内容于2017-01-09).  An article explaining why Windows 7 SP1 ignores SafeSEH for some older binaries, while Windows XP SP3 honors it.
  • MSDN:Structured Exception Handling Functions (页面存档备份,存于互联网档案馆

结构化异常处理, 是windows操作系统上, microsoft对c, 程序语言做的语法扩展, 用于处理异常事件的程序控制结构, 异常事件是打断程序正常执行流程的不在期望之中的硬件, 软件事件, 硬件异常是cpu抛出的如, 除0, 数值溢出等, 软件异常是操作系统与程序通过raiseexception语句抛出的异常, microsoft扩展了c语言的语法, except与try, finally语句来处理异常, 异常处理程序可以释放已经获取的资源, 显示出错信息与程序内部状态供调试, 从错误中恢复, 尝试重新执行. 结构化异常处理 是Windows操作系统上 Microsoft对C C 程序语言做的语法扩展 用于处理异常事件的程序控制结构 异常事件是打断程序正常执行流程的不在期望之中的硬件 软件事件 硬件异常是CPU抛出的如 除0 数值溢出等 软件异常是操作系统与程序通过RaiseException语句抛出的异常 Microsoft扩展了C语言的语法 用 try except与try finally语句来处理异常 1 异常处理程序可以释放已经获取的资源 显示出错信息与程序内部状态供调试 从错误中恢复 尝试重新执行出错的代码或者关闭程序等等 一个 try语句不能既有 except 又有 finally 但try except与try finally语句可以嵌套使用 目录 1 try except 2 try finally语句 3 执行顺序 4 例子 5 与Windows异常处理机制的关系 6 SAFESEH 7 相关的Windows API函数 8 Visual C 编译选项 9 参考文献 10 外部链接try except 编辑 try 受保护执行的代码 except 过滤表达式 异常处理代码 首先 try复合语句中的受保护的代码被执行 如果没有异常发生 则继续执行 except复合语句之后的代码 如果 try复合语句中的受保护执行的代码发生了异常 或受保护执行的代码调用的函数内部发生了异常并要求调用者来处理该异常 except语句的过滤表达式 filter expression 被求值 根据其结果来决定如何处理异常 EXCEPTION CONTINUE EXECUTION 1 导致异常的问题已经解决 在异常出现的现场重新执行操作 EXCEPTION CONTINUE SEARCH 0 当前 except语句不能处理该异常 通知操作系统继续搜寻该线程其他的异常处理程序 EXCEPTION EXECUTE HANDLER 1 当前 except语句识别该异常 通过执行 except的复合语句来处理该异常 然后执行 except复合语句之后的代码 内在函数GetExceptionCode返回一个32位整型值 表示异常的类型 内在函数GetExceptionInformation返回异常的详细信息及现场信息 如CPU寄存器的值 这两个函数可用于异常表达式中来判断是否处理该异常 这里说的内在函数 intrinsic function 是指编译器提供内联 inline 实现的函数 Windows操作系统的应用程序的main 函数受到结构化异常的try except语句保护 因此程序的未被处理的异常都会被捕获 这是因为 Windows操作系统在加载用户进程时 Kernel32 dll中的BaseProcessStart函数在 try块中调用了用户进程的入口函数mainCRTStartup 因此用户程序的所有异常都会被捕获 得到处理 可以使用C 运行时库中的 set se translator 函数把结构化异常转为抛出一个C 对象的C 异常 此外 C 异常的catch 语句也能直接捕捉结构化异常 可以使用操作系统运行时库kernel32中的SetUnhandledExceptionFilter 函数设置顶层未处理异常过滤器 top level unhandled exception filter 捕获进程的各个线程中一切未被处理的结构化异常 该函数一般用于从特定的错误中恢复 如无效的调用栈 invalid stack try finally语句 编辑 try 受保护执行的代码 finally 清理用途的代码 try复合语句中受保护的代码以任何方式执行结束后 不论 try复合语句是因为出现异常而非正常结束 还是没有出现异常而正常结束 finally复合语句中的代码都会被执行 如果 try复合语句中受保护的代码的执行没有出现异常 包括用goto语句或longjump系统函数跳出 try复合语句等情形 这时将执行 finally复合语句 然后执行try finally语句之后的其他代码 在 finally复合语句中使用内在函数AbnormalTermination判断是正常结束还是非正常结束 try复合语句 执行顺序 编辑如果 try复合语句中受保护的代码执行中出现了异常 首先按函数调用顺序从新向旧搜索所有包含了出现异常的执行点的try except语句 执行每个except的过滤函数 直到某个try except语句的过滤函数结果值为EXCEPTION EXECUTE HANDLER 这时 再从包含异常出现的执行点的最内层try finally语句开始由内向外执行每个finally块中的代码 直至回退到那个过滤函数结果值为EXCEPTION EXECUTE HANDLER的try except语句执行其except块 最后执行该try except语句后面的其他代码 leave关键字用在 try finally 语句的受保护节 try块 中 其效果是跳转到受保护节的结尾处 与goto语句跳出受保护节不同 leave语句更为有效 因为它不会导致堆栈展开 例子 编辑 include lt stdio h gt include lt windows h gt for EXCEPTION ACCESS VIOLATION include lt excpt h gt int filter unsigned int code struct EXCEPTION POINTERS ep printf 在異常表達式中 n if code EXCEPTION ACCESS VIOLATION printf 接受處理訪問違例異常 n return EXCEPTION EXECUTE HANDLER else printf 其他異常都不處理 n return EXCEPTION CONTINUE SEARCH int main int p 0x00000000 pointer to NULL printf 開始主程序 n try printf 進入外層的try n try printf 進入內層的try n int p 0 空指針 p 13 導致訪問衝突異常 finally printf 在finally內部 printf AbnormalTermination 非正常終止 n 正常終止 n except filter GetExceptionCode GetExceptionInformation printf 在except內部 n printf 主函數結束 n 輸出結果為 開始主程序 進入外層的try 進入內層的try 在異常表達式中 接受處理訪問違例異常 在finally內部 非正常終止 在except內部 主函數結束与Windows异常处理机制的关系 编辑Windows操作系统 自Windows95起 对每个用户线程 都设立一个异常处理帧链表来处理异常事件 该链表的每个异常处理帧由两个成员组成 分别是链表上一项地址 当前异常处理器地址 组成了结构 EXCEPTION REGISTRATION RECORD 异常处理器是指一个处理异常的回调函数 callback function 线程信息块 thread information block 的开始处 即FS 0 指向的内存 FS是CPU的一个段寄存器 保存了异常处理帧链表的表头项的地址 程序执行遇到异常事件而中断时 操作系统的RtlDispatchException函数会从FS 0 指向的链表表头依次调用每个节点包含异常处理回调函数 直到某个异常处理回调函数的返回值为0表示已经处理该异常 该线程可以恢复执行 链表最末一项是操作系统在装入线程时设置的指向kernel32 UnhandledExceptionFilter函数 该函数总是向用户显示 Application error 对话框 上述异常处理器程序及链表 是由用户程序自己安装的 链表各节点保存在程序调用栈 call stack 上 Windows异常处理机制支持嵌套异常的处理 即在执行异常处理回调函数时再次发生异常 这种情况下仍遵照普通异常处理机制 操作系统RtlDispatchException函数再入处理新出现的嵌套的异常 嵌套的异常的处理函数得到的DispatcherContext参数值即为在执行时发生了新异常的异常帧的地址 各种编程语言基于上述Windows异常处理机制 设计了各自的异常处理语句控制结构 Microsoft扩展了C语言语法 设计了结构化异常处理的try except与try finally语句 一个函数的所有在函数的的try except与try finally形成了一个基于包含 enclosing 关系的森林 数据结构 一个函数内如果有 try语句 则在函数的入口与结尾处 编译器插入了EH prolog与EH epilog代码 把函数内所有在try块中被保护的代码包了起来 EH prolog在调用栈上创建一个 EXCEPTION REGISTRATION RECORD 作为异常处理链表的新的表头 其中包含了Visual C 的运行时库msvcrt dll的 except handler4函数地址 在函数块的结尾处 EH epilog把这项 EXCEPTION REGISTRATION RECORD从链表头移除 恢复其原来的表头 except语句中的过滤表达式 由挂在链表中的异常处理回调函数MSVCR100D except handler4来调用执行 返回值即为过滤表达式的求值结果 实际上 编译器实现结构化异常时 把链表每项的数据结构由2个成员扩展为5个成员 即在高地址方向追加了一个scopetable entries类型结构体数组的指针 一个整型项表示执行点位于当前函数的哪个try块中 一个保存寄存器EBP的整数项 此后 低地址方向 紧接着是一个指向EXCEPTION POINTERS结构的指针 前述的内在函数GetExceptionInformation即返回这个指针值 异常发生时 操作系统的异常处理机制的ntdll RtlDispatchException函数会从FS 0 指向的链表表头依次调用异常帧链表的每个节点所包含的异常处理回调函数MSVCR100D except handler4 根据该回调函数的返回值来确定异常是否已经被处理 可以根据异常上下文 Exception context 恢复线程的执行 except handler4回调函数实际上只是调用了MSVCR100D except handler4 common函数 except handler4 common函数是实际的workhorse 负责在当前异常帧所在的函数中查找那个try except语句能够处理该异常 即过滤表达式的结果为1 2 如果不存在这样的try except块 except handler4 common函数返回ExceptionContinueExecution 值0 由RtlDispatchException继续访问异常帧链表的下一个节点 如果找到了能处理当前异常的try except块 except handler4 common函数首先调用全局展开函数 EH4 GlobalUnwind 把从异常帧链表表头所在的函数 直到能处理当前异常的函数的下一层函数 都做栈展开 unwinding 然后 对能处理当前异常的函数 从包含执行点的最内存 try语句 直到能处理异常的try except块 调用局部展开函数 EH4 LocalUnwind 再执行能处理异常的try except块的异常处理代码 最后 继续执行try except之后的其他代码 全局展开 是由 EH4 GlobalUnwind调用ntdll RtlUnwind RtlUnwind遍历访问异常帧链表 把从表头帧到目标帧 不含 的所有异常处理回调函数用异常码 STATUS UNWIND 即0C0000027H 异常标志 EXCEPTION UNWINDING即值2 调用 异常处理回调函数根据当前的异常码与异常标志 对当前异常帧所在函数 从包含了产生异常的执行点的最内层 try语句开始 直至函数内的最外层try块 依次调用try finally的清理用途代码 这一步实际上是调用 EH4 LocalUnwind函数来完成 局部展开 由 EH4 LocalUnwind函数实现 是从包含了产生异常的执行点的最内层 try语句开始 按着代码的包含关系向外直至目标try except语句为止 依次调用try finally的清理用途代码 SAFESEH 编辑为了防止篡改异常处理函数的地址 自Windows XP SP2起引入了检查异常处理函数的地址是否有效 但这仅用于x86 而x64或ARM已经把所有异常处理函数放在了PDATA节中 该节叫做 pdata 或者Exception Directory 用于存放处理异常的信息 3 链接器选项 SAFESEH NO 用于设置是否需要开启 如果 SAFESEH被使用 链接器生成的可执行映像文件 image 包含它的安全的异常处理函数的清单 如果 SAFESEH未使用 链接器将检查如果所有的模块都兼容于安全的异常处理函数特性 则生成的可执行映像文件 image 包含它的安全的异常处理函数的清单 如果有模块不兼容于安全的异常处理函数特性 则生成的可执行映像文件 image 不包含安全的异常处理函数的清单 如果 SAFESEH NO被使用 链接器生成的可执行映像文件 image 不包含安全的异常处理函数的清单 相关的Windows API函数 编辑函数 描述ExRaiseStatus 用指定状态代码触发异常ExRaiseAccessViolation 触发STATUS ACCESS VIOLATION异常ExRaiseDatatypeMisalignment 触发STATUS DATATYPE MISALIGNMENT异常Visual C 编译选项 编辑Visual C 编译器的编译选项 EH设置异常处理模型 Exception Handling Model a 捕捉异步 asynchronous或structured 与同步 synchronous或C 异常 C 的catch 语句也可捕捉异步异常 不论同步异常还是异步异常 所有局部变量对象都被自动析构 clr隐式包含了 EHa s 只捕捉同步 synchronous或C 异常 并假定使用extern C 声明的函数可能抛出异常 C 的catch 语句不捕捉异步异常 异步异常不会导致C 局部对象被自动析构 c 对于 EHsc 只捕捉同步 synchronous或C 异常 并假定使用extern C 声明的函数不会抛出C 异常 对于 EHca 等价于 EHa r 编译器对所有noexcept函数总是产生运行时终止检查代码 如果未指定 EH 则编译器将同时捕获异步结构化异常和 C 异常 但不会销毁由于异步异常超出范围的 C 对象 参考文献 编辑 Microsoft Corp Structured Exception Handling Functions MSDN Library 11 12 2009 2009 11 17 原始内容存档于2010 03 06 请检查 date 中的日期值 帮助 Microsoft Journal 上的 except handler3函数的伪代码 2013 07 01 原始内容存档于2012 12 14 MSDN SAFESEH Image has Safe Exception Handlers 2017 02 14 原始内容存档于2017 02 14 外部链接 编辑Igor Skochinsky Reversing Microsoft Visual C Part I Exception Handling OpenRCE Monday March 6 2006 12 02 38 CST 2009 11 17 原始内容存档于2010 04 16 请检查 date 中的日期值 帮助 Microsoft Corp Structured Exception Handling MSDN Library 2009 11 12 2009 11 17 原始内容存档于2009 12 08 Matt Pietrek A Crash Course on the Depths of Win32 Structured Exception Handling MSJ Jan 1997 12 1 2013 06 30 原始内容存档于2015 09 29 Note that the examples given there do not work as is on modern Windows systems post XP SP2 due to the changes Microsoft made to address the security issues present in the early SEH design The examples still work on later versions of Windows if compiled with link safeseh no win32 Safe Structured Exception Handling Yasm manual 2017 02 14 原始内容存档于2017 01 07 US patent 7 480 919 Safe exceptions Johannes Passing Fun with low level SEH May 20 2008 2017 02 14 原始内容存档于2017 02 15 Covers the obscure details needed to get low level SEH and particularly SafeSEH code to work on more modern Windows Igor Skochinsky Reversing Microsoft Visual C Part I Exception Handling OpenRCE Monday March 6 2006 12 02 38 CST 2009 11 17 原始内容存档于2010 04 16 请检查 date 中的日期值 帮助 Matt Miller Preventing the Exploitation of Structured Exception Handler SEH Overwrites with SEHOP Technet 2 Feb 2009 2017 02 14 原始内容存档于2014 07 01 Stefan Le Berre Damien Cauquil Bypassing SEHOP PDF Sysdream 22 Dec 2009 原始内容 PDF 存档于2012 09 07 Joshua J Drake Old Meets New Microsoft Windows SafeSEH Incompatibility 10 Jan 2012 2017 02 14 原始内容存档于2017 01 09 An article explaining why Windows 7 SP1 ignores SafeSEH for some older binaries while Windows XP SP3 honors it MSDN Structured Exception Handling Functions 页面存档备份 存于互联网档案馆 取自 https zh wikipedia org w index php title 结构化异常处理 amp oldid 62892994, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。