- 浏览: 342478 次
- 性别:
- 来自: 福建福州
文章分类
最新评论
-
jw72jw:
最后这个是打表求值
LUA源码分析三:table分析(1) -
dyllove98:
"一些非常重要的问题,涉及面少。那这个时候,我更崇尚 ...
乱写:团队里的独裁和民主一点看法 -
jvmlover:
被踩10次了,什么思想感情啊。
LUA源码分析三:table分析(1) -
chenchenfly99:
chenchenfly99 写道
MMO游戏终极内测开服一周,问题记录 -
chenchenfly99:
...
MMO游戏终极内测开服一周,问题记录
节一:终止处理(Termination Handlers)
节二:异常处理(Exception Handling)
节三:其他参考函数和总结
(不喜欢节前代码的直接往下拉)
节一:终止处理(Termination Handlers)
可以看出SHE在一切企图退出try块但是不退出函数体,之前插入jmp到__finally中的汇编然后清空自己堆栈,再返回下文的处理;
对于退出函数体的代码(return),拆了两部分,执行到mov eax 返回值,然后把行为交给__finally;
对于exit之类的结束函数,直接返回。
而__finally中的处理是把__finally中的代码当成一个函数调用,返回后(直接一个ret指令,非常的简洁),其中的行为全部按正常行为执行。(比如这里如果有return 就直接返回)。 然后跳回到try的上下文中。
In fact, it is always best to remove all returns, continues, breaks, gotos, and so on from inside both the try and finally blocks of a termination handler and to put these statements outside the handler.
以上就是__try的一些大致的原理.进行汇编跟调的话,很容易的发现call @ILT+240(__local_unwind4) (4110F5h)总是执行了许多繁杂的代码。这又钩了C/C++程序员效率问题唧唧喳喳的老毛病。微软提供了配套的__leave关键字:
节二:Exception Handling(异常处理)
=========代码段一==========
=========代码段二==========
1、如何跳转
except跳转有点奇怪,不像__finally有个典型的call或者__leave的jmp式。在VC里调试,而是直接从你出现异常的语句上跳到except中。
2、except后语句从哪儿开始执行?
一般来说,我们在except都会放一些保护的措施。但如果说try里的代码块越多,产生的错误性就越未知,except的保护措施就越没有针对性。对于有把握的可以参考 EXCEPTION_CONTINUE_HANDLER返回值。EXCEPTION_CONTINUE_HANDLER恰是认为你有把握处理出现的异常,并且重新执行产生异常的语句。
无把握的,或许觉得直接返回或者干脆直接跳到except后更保险,可以参考EXCEPTION_EXECUTE_HANDLER 关键字。
3、except的等级规划
具体的图在windows核心编程里非常清楚。这里稍微综述下:当异常发生的原则是,先寻找离它最近的_except块。确定返回的是EXCEPTION_EXECUTE_HANDLER,才会到原来的地方继续执行其他的一些保护函数(俗称展开)。比如except和finally一起用,并且finally是except的一个子类,则finally先调用,然后再回到except里(看代码一)。这也是应该的,finally的规则就是只要不是exit之类的函数,就必须先执行爷的,况且你调用爷,爷没执行完你敢抛弃爷?
如果是except里有个except,比如代码二,执行完子类的except后就回不到调用函数了。
节三:其他参考函数
前面的一些函数功能已经足已我的使用。也不用为没掌握剩余的而自我烦恼。如果你能将整本windows核心编程的内容都在一个应用程序里表示出来,除了要写一个完整的OS,我实在想不出来还有什么得需要如此的应用。
其余的关键字有EXCEPTION_CONTINUE_HANDLER,EXCEPTION_CONTINUE_SEARCH.获取异常的信息函GetExceptionCode,GetExceptionInformation.
另注:GetExceptionInformation可以帮你打印出程序崩溃时的调用堆栈信息(附件中特意包含,不过下载处已经忘记了,向原作者表示抱歉)。比如著名的内存溢出检测库VLD等。
在网上查找SEH的资料时,发现非常深也非常浅,深包括整个异常链表的串联等(我看了下原文是97年微软的连接),但我觉得一些机制地方如果能理解汇编的方式就算是足够了;浅包括除了搜索结果很少,一些程序员论坛提问的方式也仅仅是异常怎么用。从表现形式来说,复杂的SEH机制还不如返回值的判断来得直接。而此番学习,是因为游戏服务器的一些架构复杂的逻辑因素太多,经常会有空指针等操作。当然,这些问题都要暴露出来才能解决,但是不能以服务器当掉做为代价。况且一些复杂的多个依赖对象创建,一些异常情况的判断,用一些SEH结构可以表示得更简洁和高效。
这里感谢《windows 核心编程 5th》一书,讲得非常全面和细致。我最喜欢的是下面这段话:
However, keep in mind that the process might be unstable because an exception was raised. So it is advisable to keep the code inside the filter relatively simple[/size]
节二:异常处理(Exception Handling)
节三:其他参考函数和总结
(不喜欢节前代码的直接往下拉)
节一:终止处理(Termination Handlers)
__try { //如果是return,会先保存当前返回值,不受__finally影响 } __finally { //除了exit,terminateProcess, terminateThread,这里必执行 }
int fun_1() { 004114E0 push ebp 004114E1 mov ebp,esp 004114E3 push 0FFFFFFFEh 004114E5 push offset ___rtc_tzz+108h (418BC8h) 004114EA push offset @ILT+145(__except_handler4) (411096h) //压入异常的函数地址 004114EF mov eax,dword ptr fs:[00000000h] 004114F5 push eax 004114F6 add esp,0FFFFFF2Ch 004114FC push ebx 004114FD push esi 004114FE push edi 004114FF lea edi,[ebp-0E4h] 00411505 mov ecx,33h 0041150A mov eax,0CCCCCCCCh 0041150F rep stos dword ptr es:[edi] 00411511 mov eax,dword ptr [___security_cookie (419010h)] 00411516 xor dword ptr [ebp-8],eax 00411519 xor eax,ebp 0041151B push eax 0041151C lea eax,[ebp-10h] 0041151F mov dword ptr fs:[00000000h],eax int dwTemp = 0; 00411525 mov dword ptr [ebp-20h],0 while (dwTemp < 10) { 0041152C cmp dword ptr [ebp-20h],0Ah 00411530 jge $LN12+0Bh (411592h) __try { 00411532 mov dword ptr [ebp-4],0 if (dwTemp == 2) 00411539 cmp dword ptr [ebp-20h],2 0041153D jne fun_1+74h (411554h) continue; 0041153F push 0FFFFFFFEh 00411541 lea eax,[ebp-10h] 00411544 push eax 00411545 push offset ___security_cookie (419010h) 0041154A call @ILT+165(__local_unwind4) (4110AAh) //很复杂的异常调用,最后跳到finally 0041154F add esp,0Ch //还原异常调用堆栈 00411552 jmp fun_1+4Ch (41152Ch) if (dwTemp == 3) 00411554 cmp dword ptr [ebp-20h],3 00411558 jne fun_1+8Fh (41156Fh) break; 0041155A push 0FFFFFFFEh 0041155C lea eax,[ebp-10h] 0041155F push eax 00411560 push offset ___security_cookie (419010h) 00411565 call @ILT+165(__local_unwind4) (4110AAh) //很复杂的异常调用,最后跳到finally 0041156A add esp,0Ch 0041156D jmp $LN12+0Bh (411592h) } __finally { 0041156F mov dword ptr [ebp-4],0FFFFFFFEh 00411576 call $LN9 (41157Dh) //执行__finally里的代码 0041157B jmp $LN12 (411587h) //跳到正常的while结尾 dwTemp++; 0041157D mov eax,dword ptr [ebp-20h] 00411580 add eax,1 00411583 mov dword ptr [ebp-20h],eax $LN10: 00411586 ret } dwTemp++; 00411587 mov eax,dword ptr [ebp-20h] 0041158A add eax,1 0041158D mov dword ptr [ebp-20h],eax } 00411590 jmp fun_1+4Ch (41152Ch) dwTemp += 10; 00411592 mov eax,dword ptr [ebp-20h] 00411595 add eax,0Ah 00411598 mov dword ptr [ebp-20h],eax return(dwTemp); 0041159B mov eax,dword ptr [ebp-20h] } try块中的return; return i; 004117F3 mov eax,dword ptr [ebp-20h] 004117F6 mov dword ptr [ebp-0ECh],eax 004117FC push 0FFFFFFFEh 004117FE lea ecx,[ebp-10h] 00411801 push ecx 00411802 push offset ___security_cookie (41F040h) 00411807 call @ILT+240(__local_unwind4) (4110F5h) //执行__finally中函数
可以看出SHE在一切企图退出try块但是不退出函数体,之前插入jmp到__finally中的汇编然后清空自己堆栈,再返回下文的处理;
对于退出函数体的代码(return),拆了两部分,执行到mov eax 返回值,然后把行为交给__finally;
对于exit之类的结束函数,直接返回。
而__finally中的处理是把__finally中的代码当成一个函数调用,返回后(直接一个ret指令,非常的简洁),其中的行为全部按正常行为执行。(比如这里如果有return 就直接返回)。 然后跳回到try的上下文中。
In fact, it is always best to remove all returns, continues, breaks, gotos, and so on from inside both the try and finally blocks of a termination handler and to put these statements outside the handler.
以上就是__try的一些大致的原理.进行汇编跟调的话,很容易的发现call @ILT+240(__local_unwind4) (4110F5h)总是执行了许多繁杂的代码。这又钩了C/C++程序员效率问题唧唧喳喳的老毛病。微软提供了配套的__leave关键字:
__leave; 0041152F jmp fun_1+76h (411556h)
节二:Exception Handling(异常处理)
__try { } __except( EXCEPTION_EXECUTE_HANDLER ) { }
=========代码段一==========
int fun_finally() { __try { int i=0; i/=i; cout<<"fun_finally:try"<<endl; } __finally { cout<<"fun_finally::finally"<<endl; } return 0; } int fun_exception() { int i; __try { fun_finally(); } __except( EXCEPTION_EXECUTE_HANDLER ) { cout<<"fun_exception:except"<<endl; } return 0; } int _tmain(int argc, _TCHAR* argv[]) { fun_exception(); return 0; }
=========代码段二==========
void fun_exception_2(); void fun_exception_1() { __try { fun_exception_2(); } __except( EXCEPTION_EXECUTE_HANDLER ) { cout<<"fun_exception_1"<<endl; } } void fun_exception_2() { __try { int i=0; i/=i; } __except( EXCEPTION_EXECUTE_HANDLER ) { cout<<"fun_exception_2"<<endl; } } int _tmain(int argc, _TCHAR* argv[]) { fun_exception_1(); return 0; }
1、如何跳转
except跳转有点奇怪,不像__finally有个典型的call或者__leave的jmp式。在VC里调试,而是直接从你出现异常的语句上跳到except中。
2、except后语句从哪儿开始执行?
一般来说,我们在except都会放一些保护的措施。但如果说try里的代码块越多,产生的错误性就越未知,except的保护措施就越没有针对性。对于有把握的可以参考 EXCEPTION_CONTINUE_HANDLER返回值。EXCEPTION_CONTINUE_HANDLER恰是认为你有把握处理出现的异常,并且重新执行产生异常的语句。
无把握的,或许觉得直接返回或者干脆直接跳到except后更保险,可以参考EXCEPTION_EXECUTE_HANDLER 关键字。
3、except的等级规划
具体的图在windows核心编程里非常清楚。这里稍微综述下:当异常发生的原则是,先寻找离它最近的_except块。确定返回的是EXCEPTION_EXECUTE_HANDLER,才会到原来的地方继续执行其他的一些保护函数(俗称展开)。比如except和finally一起用,并且finally是except的一个子类,则finally先调用,然后再回到except里(看代码一)。这也是应该的,finally的规则就是只要不是exit之类的函数,就必须先执行爷的,况且你调用爷,爷没执行完你敢抛弃爷?
如果是except里有个except,比如代码二,执行完子类的except后就回不到调用函数了。
节三:其他参考函数
前面的一些函数功能已经足已我的使用。也不用为没掌握剩余的而自我烦恼。如果你能将整本windows核心编程的内容都在一个应用程序里表示出来,除了要写一个完整的OS,我实在想不出来还有什么得需要如此的应用。
其余的关键字有EXCEPTION_CONTINUE_HANDLER,EXCEPTION_CONTINUE_SEARCH.获取异常的信息函GetExceptionCode,GetExceptionInformation.
另注:GetExceptionInformation可以帮你打印出程序崩溃时的调用堆栈信息(附件中特意包含,不过下载处已经忘记了,向原作者表示抱歉)。比如著名的内存溢出检测库VLD等。
在网上查找SEH的资料时,发现非常深也非常浅,深包括整个异常链表的串联等(我看了下原文是97年微软的连接),但我觉得一些机制地方如果能理解汇编的方式就算是足够了;浅包括除了搜索结果很少,一些程序员论坛提问的方式也仅仅是异常怎么用。从表现形式来说,复杂的SEH机制还不如返回值的判断来得直接。而此番学习,是因为游戏服务器的一些架构复杂的逻辑因素太多,经常会有空指针等操作。当然,这些问题都要暴露出来才能解决,但是不能以服务器当掉做为代价。况且一些复杂的多个依赖对象创建,一些异常情况的判断,用一些SEH结构可以表示得更简洁和高效。
这里感谢《windows 核心编程 5th》一书,讲得非常全面和细致。我最喜欢的是下面这段话:
However, keep in mind that the process might be unstable because an exception was raised. So it is advisable to keep the code inside the filter relatively simple[/size]
- StackWalkInC.rar (12.8 KB)
- 下载次数: 2
发表评论
-
linux内存分配slub的几个疑问
2011-01-13 08:21 1704对于SLUB不熟的同学可以 ... -
开源一个windows下的内存分配器slab,
2010-10-28 20:23 1457模仿linux内核下的slab而写。一些地址页面做了些新的工作 ... -
网络编程中缓冲带来的异步以及需要设置(windows)
2010-08-08 03:50 0此次的疑问主要来自IOCP下的程序编写。 WINDOWS下的 ... -
小议内存池、资源池
2010-08-02 21:08 2197比较简单的一篇文章。本来是有些地方没想明白,想分析一下。结果写 ... -
(00XX系列)抽抽Windows宽字符的棉絮(附日志文件源码)
2009-11-21 17:18 1266爷最近和可 ... -
配置主机无线网络+虚拟机linux的上网
2009-09-05 11:04 4872环境如下: windows2003主机,虚拟机VM精简版,装有 ... -
碎片:linux vs windows, 内存/硬盘
2009-08-23 13:12 1679找了一堆资料,稍微整 ... -
详解sigaction
2008-12-18 22:24 10608本杂文主要是讲解了下信号和进程的关系。前面主要是一些man式的 ... -
分析《进程间通信》一书中的读/写锁策略
2008-08-27 17:00 3429以下代码和资料均学习自:《进程间通信》第8章读写锁 其中附件中 ... -
基础:systemV 信号 create send recv rmid
2008-07-26 17:30 1236/* @gcc version 3.2.2 200302 ... -
让您轻松理解execl函数系列 ^_^
2008-06-19 20:03 6883execl函数功能如下:启动一个可执行文件,并且对他进行传送参 ... -
[收集 转载]关于Linux下编写和编译程序的几个问题
2008-04-23 09:09 1921FROM http://www.fmm7.com/jsjc/w ... -
资料存放 linux命令收集和问题记录
2008-03-30 23:03 1468rm -rf name //递归删除 -
Linux基本目录用途
2008-03-24 10:19 2013/bin 该目录中存放Linux的常用命令,在有的版本中是一 ... -
在CentOS 4.4下安装gcc--RPM
2008-03-23 22:28 3397yum install gcc(需要的组件,即你也可以下载以下 ... -
资料存放 yum
2008-03-23 20:47 1101使用 yum 升级和 yum 使用 ... -
资料存放 tar
2008-03-23 20:46 1111tar命令 tar可以为文件和目录创建档案。利用tar,用户可 ... -
初学LINUX:架设一个 VSFTPD服务器系列
2008-03-09 01:33 1605实习的公司需要用到 LINUX,而自己也想深入这方面 公司用的 ... -
虚拟机中设置linux连接网络
2008-03-01 17:21 3862虚拟机:vmware Linux版本:CentOS(版本不会造 ... -
CentOS资料分类
2008-02-08 16:30 1796http://centos.ustc.edu.cn/CentO ...
相关推荐
本文将深入探讨SEH的工作原理、其在Windows程序设计中的应用,以及如何有效地利用SEH来提高程序的健壮性。 ### 1. 结构化异常处理基础 #### 1.1 异常的概念 异常是程序执行过程中遇到的非正常情况,它可以是硬件...
SEH系列:代码文件3
SEH系列:代码文件2
SEH系列:代码文件1
在Windows平台上,SEH(Structured Exception Handling)是一种用于处理程序异常的技术,而libcc_s_seh-1.dll就是实现这一功能的关键组件。 当您尝试运行某个应用程序时,如果系统提示“找不到libcc_s_seh-1.dll”...
然而,SEH引入了一个异常链表(Exception Handler Chain),这个链表包含了程序预先定义的一系列异常处理函数,按照优先级顺序排列。当异常发生时,系统会沿着这个链表寻找合适的处理程序来恢复或处理异常,而不是...
对于C++开发者来说,理解两种主要的异常处理方式——C++标准异常处理机制(`try-catch`)与特定于Windows平台的结构化异常处理(Structured Exception Handling, SEH)——之间的区别尤为重要。本文将深入探讨这两种...
在Windows操作系统中,SEH是一种处理程序运行时异常的标准机制。这个"seh结构化处理易语言模块源码"提供的是用易语言编写的模块,用于理解和实现SEH机制。 易语言是一款中国本土开发的、以中文编程为特色的编程语言...
描述中提到的"win32汇编 SEH实现的远程调用call"指出,此技术应用于32位Windows系统,尽管标题提及的是64位环境,但描述中的"win32汇编"可能是指在32位上下文中讨论的SEH技术。远程调用call是指在一个进程中执行的...
综合上述信息,"x86-64-13.2.0-release-posix-seh-rev1.7z" 这个压缩包提供的工具集允许开发者在Windows 64位环境下使用GCC和G++进行跨平台编程,尤其是对于那些希望在Windows系统上开发与Unix/Linux系统兼容的C++...
SEH,全称为Structured Exception Handling(结构化异常处理),是微软在Windows操作系统中引入的一种异常处理机制。在编程过程中,异常处理是必不可少的部分,它帮助我们处理程序运行时可能出现的各种错误或异常...
结构化异常处理是Windows操作系统中的一种机制,用于处理程序运行时可能出现的各种异常情况,如除零错误、访问非法内存等。在C++和汇编语言中,SEH是非常重要的异常处理方式。在易语言中,虽然其语法与传统编程语言...
总结来说,x86-64-posix-seh是Windows 64位平台上的异常处理机制,而MinGW-W64是用于在Windows上构建64位程序的工具集,两者结合使用,可以帮助开发者在Windows环境中编写、编译和调试与POSIX兼容的64位程序。...
win异常处理SEH教程.zip 先天型SEH 后天型SEH VEH C++ EH
SEH(Structured Exception Handling)是Windows操作系统中用于处理异常的一种机制,它为程序员提供了控制异常处理流程的能力。本教程“C++ SEH HOOK拦截任意API 1G视频教程”显然专注于利用C++中的SEH技术来实现API...
MingW_x86_64-Posix-SEH是一个针对Windows操作系统的开发工具集,主要为64位架构设计,用于编译C和C++程序。MingW(Minimalist GNU for Windows)是一个开源项目,它将GNU编译器集合(GCC)和其他GNU工具移植到...
在Windows环境中,有多种方法来实现API Hook,其中一种是使用结构化异常处理(Structured Exception Handling, 简称SEH)。本篇文章将深入探讨如何利用SEH技术来实现API Hook。 首先,我们需要理解SEH的基本概念。...
SEH反调试.rar
西门子 SEH62.1 时控开关设置说明 西门子 SEH62.1 时控开关是一种微处理器控制的时控开关装置,具有自动存储编程时间的功能。该装置可以根据时间程序自动动作,并具有手动开关、手动关、可调倒计时定时开四种模式。...
SEH是微软Windows操作系统中的一种异常处理框架,它提供了一种有序的方式来捕获和处理程序执行过程中的异常。在易语言中,我们可以通过设置异常处理来确保程序在遇到错误时不会立即崩溃,而是能够优雅地处理异常并...