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

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

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

Funcenstein4

Let's take a look at one more termination-handling scenario:

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

      g_dwProtectedData = 5;
      dwTemp = g_dwProtectedData;

      // Return the new value.
      return(dwTemp);
   }
   __finally {
      // 3. Allow others to use protected data.
      ReleaseSemaphore(g_hSem, 1, NULL);
      return(103);
   }

   // Continue processing--this code will never execute.
   dwTemp = 9;
   return(dwTemp);
}

In Funcenstein4, the try block will execute and try to return the value of dwTemp
(5) back to Funcenstein4's caller. As noted in the discussion of Funcenstein2,
trying to return prematurely from a try block causes the generation of code that puts the return value into a temporary variable created by the compiler. Then the code inside the finally
block is executed. Notice that in this variation on Funcenstein2 I have added a return statement to
the finally block. Will Funcenstein4 return 5
or 103 to the caller? The answer is 103 because the return
statement in the finally block causes the value 103 to be stored in the same temporary variable in which
the value 5 has been stored, overwriting the5. When the finally
block completes execution, the value now in the temporary variable (103) is returned from Funcenstein4
to its caller.

本例中,try部分将返回dwTemp(值为5)。如前所述,在try中的return会导致编译器产生额外的代码用来把返回值放到一个临时变量里,然后去执行finally中的内容。与前面的例子不同的是,本例在finally里增加了一个return,这次会返回5还是103呢?答案是103,因为finally中dereturn导致103保存到了刚才保存5的临时变量。

We've seen termination handlers do an effective job of rescuing execution from a premature exit of the try block, and we've also seen termination handlers produce
an unwanted result because they prevented a premature exit of the try block. A good rule of thumb is to avoid any statements that would
cause a premature exit of the try block part of a termination handler. 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. Such a practice will cause the compiler to generate both a smaller amount of code—because it won't have to catch premature exits from the try block—and faster
code, because it will have fewer instructions to execute in order to perform the local unwind. In addition, your code will be much easier to read and maintain.

本我们看到了termination hander在try中出现提前退出时产生的后果。一条很好的原则就是,不要在try中制造提前退出。具体地讲,就是在try、finally里不要出现return、continue、break、goto。这样编译器产生的代码会少很多,而且由于不需要执行local unwind,代码执行速度也会快得多。而且,代码也会更易读、维护。

抱歉!评论已关闭.