使用/SAFESEH自定义SEH处理程序

6

我目前在尝试使用C ++创建编译器,该编译器会在运行时生成机器码。然而,我目前正在尝试启用安全异常处理(使用/SAFESEH编译)。我的自定义异常处理程序在调试模式下工作正常,但是当我在发布模式下运行相同的代码时,我的进程就会被终止。

我非常确定问题在于我未能将我的自定义异常处理程序注册为这样,因为当我使用/SAFESEH:NO编译我的代码时,即使在发布模式下,一切都正常工作。

我的自定义异常处理程序编写在我的其他C ++代码中,并尝试通过添加.asm文件到项目中来注册它,其内容如下:

.386
.model flat
_MyExceptionHandler@16 proto
.safeseh _MyExceptionHandler@16
end

根据这里描述。然后使用 /safeseh 选项(以及其他选项)对 asm 文件进行了汇编。

我的处理程序函数目前具有以下声明:

extern "C" EXCEPTION_DISPOSITION __stdcall MyExceptionHandler(struct
_EXCEPTION_RECORD *ExceptionRecord, void * EstablisherFrame, struct 
_CONTEXT *ContextRecord, void * DispatcherContext);

这个函数应该如何正确注册为异常处理程序?
谢谢任何建议!
3个回答

4
我终于找到了一个描述这个问题的页面:这里。然而,该页面中的代码示例未经修改无法正常工作。
问题似乎在于将外部过程注册为异常处理程序并没有按预期工作,因此您需要注册本地程序集过程作为异常处理程序。
根据前面提到的页面上给出的示例,以下是我最终得到的结果:
.386
.model flat, stdcall
option casemap :none

extern MyExceptionHandler@16:near

MyExceptionHandlerAsm proto
.SAFESEH MyExceptionHandlerAsm

.code
MyExceptionHandlerAsm proc
    jmp MyExceptionHandler@16
MyExceptionHandlerAsm endp
end

这种方法看起来可行,但很可能不是最优解。例如:为了避免在从C/C++引用MyExceptionHandlerAsm时出现链接错误,我不得不将其声明为:

extern "C" int __stdcall MyExceptionHandlerAsm();

如果有人试图从C/C++调用MyExceptionHandlerAsm,由于参数数量不匹配,程序将会崩溃。

这个在x64上也能工作吗?如果我使用32位VC编译器编译它,并在64位Windows上运行它,那么定制的异常处理程序会被调用吗? - jichi
只要你为x86编译它,Windows就能在32位和64位的Windows上运行32位应用程序。这是我一直在做的。但是,我还没有使用64位编译器编译代码进行测试。 - Filip

1

MSDN文档来看,您的ASM似乎是正确的。您是否在ml.exe中添加了/safeseh选项?


谢谢你的回答!是的,我在 ml.exe 中添加了 /safeseh,否则会收到警告。我也会在上面做出记录。 - Filip

0

ExceptionHandler函数的签名实际上是:

typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) (
    __in struct _EXCEPTION_RECORD *ExceptionRecord,
    __in PVOID EstablisherFrame,
    __inout struct _CONTEXT *ContextRecord,
    __inout PVOID DispatcherContext
    );

请参见此MSDN页面。相同的异常程序用于32位Windows,因此忽略文档提到的x64。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接