现在的位置: 首页 > 综合 > 正文

Chapter 23: Termination Handlers(2)Understanding Termination Handlers by Example(5)

2018年04月10日 ⁄ 综合 ⁄ 共 3853字 ⁄ 字号 评论关闭

Notes About the finally Block

So far we have explicitly identified two scenarios that force the finally block to be executed:

到目前为止,我们确定的两种导致finally执行的情形:

  • Normal flow of control from the
    try
    block into the
    finally
    block 

    正常情况,从try中进入

  • Local unwind: premature exit from the
    try
    block (goto,longjump,continue,break,
    return
    , and so on) forcing control to the finally block

    Local unwind,使用goto等导致提前退出try

A third scenario—a
global unwind
—occurred without explicit identification as such in the
Funcfurter1
function we saw on
page 663
. Inside the try block of this function was a call to the Funcinator function. Before Windows
Vista, if the Funcinator function caused a memory access violation, a global unwind caused Funcfurter1's finally
block to execute. As of Windows Vista, a global unwind is not triggered by default, so the finally block is not executed. "The SEH Termination Sample
Application
" on page 673 gives you a first glance at what triggers a global unwind, and we'll look at global unwinding in greater detail in the next two chapters.

第三种情形----global unwind----?

Code in a finally block always starts executing as a result of one of these three situations. To determine which of the three possibilities caused the finally
block to execute, you can call the intrinsic function AbnormalTermination:

可以通过函数判断是因为什么导致finally被执行

BOOL AbnormalTermination();

  Note 

An intrinsic function is a special function recognized by the compiler. The compiler generates the code for the function inline rather than generating code to call the function. For
example, memcpy is an intrinsic function (if the/Oi compiler switch is specified). When the compiler
sees a call tomemcpy, it puts thememcpy code directly into the function that calledmemcpy
instead of generating a call to thememcpy function. This usually has the effect of making your code run faster at the expense of code size.

The intrinsic AbnormalTermination function is different from the intrinsicmemcpy
function in that it exists only in an intrinsic form. No C/C++ run-time library contains theAbnormalTermination function.

This intrinsic function can be called only from inside a
finally
block, and it returns a Boolean value indicating whether the try block associated with the finally
block was exited prematurely. In other words, if the flow of control leaves the try block and naturally enters the finally
block, AbnormalTermination will return FALSE. If the flow of control exits the try
block abnormally— usually because a local unwind has been caused by a goto,return,break,
or continue statement or because a global unwind has been caused by a memory access violation or another exception— a call to AbnormalTermination
will return TRUE. It is impossible to determine whether a finally block is executing because of a global
unwind or because of a local unwind. This is usually not a problem because you have, of course, avoided writing code that performs local unwinds.

这个函数只能在finally中被调用,它的返回值表明try中的代码是否提前退出了。换句话说,如果流程是自然进入finally,这个函数返回FALSE。如果是提前退出try或者是由其他异常产生的global unwind,这个函数返回TRUE。目前没办法区别local unwind和global unwind。通常这不是问题,因为你可以在写代码的时候避免local unwind。

Funcfurter2

Here is Funcfurter2, which demonstrates use of the
AbnormalTermination intrinsic function:

DWORD Funcfurter2() {
   DWORD dwTemp;

   // 1. Do any processing here.
   ...
   __try {
      // 2. Request permission to access
      //    protected data, and then use it.
      WaitForSingleObject(g_hSem, INFINITE);

      dwTemp = Funcinator(g_dwProtectedData);
   }
   __finally {
      // 3. Allow others to use protected data.
      ReleaseSemaphore(g_hSem, 1, NULL);

      if (!AbnormalTermination()) {
         // No errors occurred in the try block, and
         // control flowed naturally from try into finally.
         ...
      } else {
         // Something caused an exception, and
         // because there is no code in the try block
         // that would cause a premature exit, we must
         // be executing in the finally block
         // because of a global unwind.

         // If there were a goto in the try block,
         // we wouldn't know how we got here.
         ...
      }
   }

   // 4. Continue processing.
   return(dwTemp);
}

Now that you know how to write termination handlers, you'll see that they can be even more useful and important when we look at exception filters and exception handlers in the
next chapter. Before we move on, let's review the reasons for using termination handlers:

  • They simplify error processing because all cleanup is in one location and is guaranteed to execute.

  • They improve program readability.

  • They make code easier to maintain.

  • They have minimal speed and size overhead if used correctly.

抱歉!评论已关闭.