EXCEPTION_CONTINUE_SEARCH

[Previous] [Next]

The examples have been pretty tame so far. Let's shake things up a bit by adding a function call:

 char g_szBuffer[100]; void FunclinRoosevelt2() { char *pchBuffer = NULL; _ _try { FuncAtude2(pchBuffer); } _ _except (OilFilter2(&pchBuffer)) { MessageBox(…); } } void FuncAtude2(char *sz) { *sz = 0; } LONG OilFilter2 (char **ppchBuffer) { if (*ppchBuffer == NULL) { *ppchBuffer = g_szBuffer; return(EXCEPTION_CONTINUE_EXECUTION); } return(EXCEPTION_EXECUTE_HANDLER); } 

When FunclinRoosevelt2 executes, it calls FuncAtude2, passing it NULL. When FuncAtude2 executes, an exception is raised. Just as before, the system evaluates the exception filter associated with the most recently executing try block. In this example, the try block inside FunclinRoosevelt2 is the most recently executing try block, so the system calls the OilFilter2 function to evaluate the exception filter—even though the exception was generated inside the FuncAtude2 function.

Now let's stir things up a little more by adding another try-except block.

 char g_szBuffer[100]; void FunclinRoosevelt3() { char *pchBuffer = NULL; _ _try { FuncAtude3(pchBuffer); } _ _except (OilFilter3(&pchBuffer)) { MessageBox(…); } } void FuncAtude3(char *sz) { _ _try { *sz = 0; } _ _except (EXCEPTION_CONTINUE_SEARCH) { // This never executes.        } } LONG OilFilter3(char **ppchBuffer) { if (*ppchBuffer == NULL) { *ppchBuffer = g_szBuffer; return(EXCEPTION_CONTINUE_EXECUTION); } return(EXCEPTION_EXECUTE_HANDLER); } 

Now when FuncAtude3 tries to fill address NULL with 0, an exception is still raised but FuncAtude3's exception filter will get executed. FuncAtude3's exception filter is very simple and evaluates to EXCEPTION_CONTINUE_SEARCH. This identifier tells the system to walk up to the previous try block that's matched with an except block and call this previous try block's exception filter.

Because FuncAtude3's filter evaluates to EXCEPTION_CONTINUE_SEARCH, the system will walk up to the previous try block (in FunclinRoosevelt3) and evaluate its exception filter, OilFilter3. OilFilter3 will see that pchBuffer is NULL, will set pchBuffer to point to the global buffer, and will then tell the system to resume execution on the instruction that generated the exception. This will allow the code inside FuncAtude3's try block to execute, but unfortunately, FuncAtude3's local sz variable will not have been changed, and resuming execution on the failed instruction will simply cause another exception to be generated. What we have here is another infinite loop!

You'll notice I said that the system walks up to the most recently executing try block that's matched with an except block and evaluates its filters. This means that any try blocks that are matched with finally blocks instead of except blocks are skipped by the system while it walks up the chain. The reason for this should be pretty obvious: finally blocks don't have exception filters and therefore give the system nothing to evaluate. If FuncAtude3 in the last example contained a finally block instead of its except block, the system would have started evaluating exception filters beginning with FunclinRoosevelt3's OilFilter3.

Chapter 25 offers more information about EXCEPTION_CONTINUE_SEARCH.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net