有这么个问题
有个读者问:当异常发生的时候,如果不知道是否要清理临界区对象,什么是合适的异常处理方式?
这个读者的问题是这样的:
“我正在使用SEH,在代码中我使用了__try/__except块来保护那些进入和退出临界区的代码。当异常发生的时候,我不知道我是否还在临界区中还是已经出来了。就算是使用__try/__finally这种方式,也没能解决我的
问题。”
问题答案:你可以知道你是否拥有临界区对象,因为你一旦进入了,就表示你获取到了临界区对象。
方法1:通过指令指针进行判断
“如果代码执行到这里,则表示我肯定在临界区里。”
请注意,以上这种方法对于嵌套调用EnterCriticalSection的情况也是能正常工作的。
如果你再次获取到了临界区,则一定要记得将调用包含在它自身的try/finally结构中。
方法2:通过栈变量进行判断
“我记得我是否已经进入临界区”
以上方法也是可以适用于嵌套调用EnterCriticalSection的情况。只是要记得,每次获取临界区对象,都要对cEntered进行加1。
方法3:通过对象来进行追踪
将CRITICAL_SECTION封装到一个对象中。
这种方法最适合上面那位读者的情况。
请注意,上面的代码,不适用于嵌套临界区的情况。如果你试着获取临界区对象两次,则异常处理器只会退出临界区一次。
还请注意,我们认为临界区在初始状态下为未获取状态并添加了断言。如果恰好已经获得了临界区,则我们的清理代码将会尝试退出临界区,但是它实际并没有进入。(试想一下,如果在第一个”…”中就出现了异常。)
方法4:通过智能对象判断
通过将CRITICAL_SECTION对象封装到一个智能对象中。
可以在上面的代码中添加如下方法:Dword Depth() { return Owned() ? m_dwDepth : 0; }
代码如下:
当异常发生在临界区的时候进行清理会导致这样一个问题:我怎么知道清理操作是安全的?
你使用到了临界区说明你想独占的使用一个数据结构,但是如果在获取临界区的时候发现了异常,此时数据结构的状态是不稳定的。如果只是简单的退出临界区会导致数据结构进入到一个不一致的状态,就会导致一个很难诊断的问题:为什么我的引用计数没有同步了?
后面我还会有更多关于异常的内容。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《How do I determine whether I own a critical section if I am not supposed to look at internal fields?》