今天终于大致了解了,SEH中关于EH_UNWINDING的作用以及,VC++编译器中异常处理的一点点小东西,老规矩先帖完整测试代码:
EN_WINDING winding的中文有一种译法叫“从缠绕中解开”,我觉得很形象,用一个例子说明EN_WINDING的作用,假设,能正确处理本例子的异常为ERX
ER链表应该是这样的: ER1->ER2->ER3->ERX->ER4->ER5
那么当异常发生的时候,遍历ER链,最后找到ERX,这个时候WINDOWS会再次遍历该ER链,这次的遍历有2个作用(就目前我所知道的部分哈)
1、释放某些因为异常导致来不及清理的资源
2、彻底断开ER链中正确处理异常的ER前的其他节点
也就是说,异常处理完毕后 ER链应该是这个样子:ERX->ER4->ER5
虽然EH_WINDINGD的作用书上都有介绍,但还是不及自己跟踪后的那种程度清晰
接下来就是一个比较有意思的发现了,就是C++中 _try 和 _except的一些小秘密,虽然封装的很严实,但还是有些马脚露出来的!
首先我们现在主函数后的那个(上下个跟踪断点,考虑在这下断,是因为想先看看程序最原始(也许并不是最,但对我们的试验不影响)的时候,ER链的情况:
ER1->ER2->END
发现了一个现象,程序刚RUN时,ER链只有2个节点,我原以为是偶然,但重起机器后发现并非偶然,而且地址固定,这个不重要.
F10单步,来到了_try处,继续步过,这个时候我们在MEMORY中查找FS:[0]值,这个值就是第一个节点也就是表头的地址,不在是原来的ER1的地址了,而是换成了另外一个地址,但这个地址确确实实是一直存在,跟踪后会发现这点,最初,我是这样大胆猜想的,_try在一开始就偷偷的在原来的ER链上挂接了一个自己的ER结构,也就是说_try执行后,ER链变成这样了:ER3->ER1->ER2->END
本来如果不是后来发现点东西,我差点就这样盖棺定论了,转折点在这:
_except( EXCEPTION_EXECUTE_HANDLER) 在此句下断,注意观察FS:[0]会发现,刚才才出现新头领ER3之前又出现了个主,我们暂且叫ER4,于是ER链变成这样了:
ER4->ER3->ER1->ER2->END
但这主(ER4)很短命,在步过这句后,就消失了,ER链又变为:
ER3->ER1->ER2->END这个发现很奇怪,我想应该是编译器处理级的内容,我暂时还不明白。
上面的代码 包含了新ER连创建的2个方法,一个是在表头创建,一个是在第一节点和第2节点之间创建,可以引申到在链中任意位置创建
不过通过上面的简单分析知道了_try总喜欢把他们的ER结构挂在表头,仿佛自己是老大,呵呵