© 2004 Microsoft Corporation. All rights reserved.

Figure 5 Custom Error Handler
/*/////////////////////////////////////////////////////////////////////
FUNCTION        :   HandleRTCFailure
DESCRIPTION     :
    The Runtime Checking (RTC) handler function when NOT running
under the debugger.  When running under a debugger, this function
is ignored.  Consequently, you can't debug this puppy at all!
PARAMETERS      :
    iError   - The type of error as reported through _RTC_SetErrorType.
               Note that I don't use this parameter.
    szFile   - The source file name where the error occurred.
    iLine    - The line where the error occurred.
    szModule - The module where the error occurred.
    szFormat - The printf-style format string for the variable
               parameters.
               Note that I don't use this parameter except to get the
               values out of the variables parameters.
    ...      - The "variable" length parameter list.  There are only
               two values passed here.  The first is the RTC Error
               number.
                    1 = /RTCc
                    2 = /RTCs
                    3 = /RTCu
                The second is the string that appears when the debugger
                shows the message.  This is only important for /RTCs and
                /RTCu as those show the variable where the problem
                happened.
RETURN VALUES   :
    TRUE  - Cause a _DebugBreak to be called after this function
            returns.
    FALSE - Continue execution.
/////////////////////////////////////////////////////////////////////*/
// Turn off run time checks for this function so I don't go recursive
// on myself.
#pragma runtime_checks("", off)

// The critical section to protect against reentrancy in the 
// HandleRTCFailure function.
CRITICAL_SECTION g_csRTCLock ;

int HandleRTCFailure ( int          /*iError*/   ,
                       const char * szFile       ,
                       int          iLine        ,
                       const char * szModule     ,
                       const char * szFormat     ,
                       ...                        )
{
    // Just say no to reentrant code!
    EnterCriticalSection ( &g_csRTCLock ) ;

    // Get the two variable length parameters.  I guess they plan on
    // adding a ton of these RTC checks in the future.
    va_list vl ;

    va_start ( vl , szFormat ) ;

    // The first one is the number of the error that occured.
    _RTC_ErrorNumber RTCErrNum = va_arg ( vl , _RTC_ErrorNumber ) ;
    
    // The second is the additional description of the error.
    char * szErrorVariableDesc = va_arg ( vl , char * ) ;

    va_end ( vl ) ;

    TCHAR szBuff [ 512 ] ;

    // Get the error description text based off the error number.
    const char *szErr = _RTC_GetErrDesc ( RTCErrNum ) ;

    // Make sure szFile and szModule have something in them.
    if ( NULL == szFile )
    {
        szFile = "Unknown File" ;
    }
    if ( NULL == szModule )
    {
        szModule = "Unknown Module" ;
    }

    // If it's any error other than /RTCc, I can show some cool info
    // that includes the variable in question!
    if ( 1 != RTCErrNum )
    {
        _stprintf ( szBuff                                        ,
                    _T ( "%S\n%S\nLine #%d\nFile:%S\nModule:%S" ) ,
                    szErr                                         ,
                    szErrorVariableDesc                           ,
                    iLine                                         ,
                    szFile                                        ,
                    szModule                                       ) ;
    }
    else
    {
        // Build the string.
        _stprintf ( szBuff                                    ,
                    _T ( "%S\nLine #%d\nFile:%S\nModule:%S" ) ,
                    szErr                                     ,
                    iLine                                     ,
                    szFile                                    ,
                    szModule                                   ) ;
    }

    int iRes = TRUE ;
    if ( IDYES == MessageBox ( GetForegroundWindow ( )          ,
                               szBuff                           ,
                               _T ( "Run Time Check Failure" )  ,
                               MB_YESNO                          ) )
    {
        // Returning TRUE means DebugBreak will happen when this
        // function returns.
        iRes = TRUE ;
    }
    else
    {
        iRes = FALSE ;
    }

    // Pop out of the lock.
    LeaveCriticalSection ( &g_csRTCLock ) ;

    return ( iRes ) ;
}
#pragma runtime_checks("", restore)
Figure 6 Optimization on Several Files

Optimizations.cpp - The Main File
// CL: /GL /O1 /Ob1 /Oy /GF /EHsc /Gy 
//////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AnotherModule.h"
#include "YetAnother.h"

void wmain ( void ) 
{
    int i = 1 ;
    int j = 2 ;
    
    InitializeVariables ( &i , &j ) ;
    
    wprintf ( L"i = %d, j = %d\n" , i , j ) ;
    
    i = InitializeTLSValues ( ) ;
    wprintf ( L"InitializeLTSValues returned %d\n" , i ) ;
    
    i = ReturnValue ( ) ;
    wprintf ( L"ReturnValue returned %d\n" , i ) ;
}
AnotherModule.cpp
// CL: /GL /O1 /Ob1 /Oy /GF /EHsc /Gy 
//////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AnotherModule.h"

__declspec ( thread ) int g_TLSInteger = 0 ;

void InitializeVariables ( int * i , int * j ) 
{
    *i = 0xA ; 
    *j = 0xB ;
}

int InitializeTLSValues ( void )
{
    g_TLSInteger = 1 ;
    return ( g_TLSInteger ) ;
}
YetAnother.cpp
// CL: /GL /O1 /Ob2 /Oy /GF /EHsc /Gy 
//////////////////////////////////////////////////////////////
#include "stdafx.h"

int ReturnValue ( void )
{
    return ( 0xBB ) ;
}
Figure 7 wmain Disassembly for Version 6.0
wmain:
00401000:   push      ebp
00401001:   mov       ebp,esp
00401003:   push      ecx
00401004:   push      ecx
00401005:   lea       eax,dword ptr [ebp-008h]
00401008:   push      esi
00401009:   push      eax
0040100A:   lea       eax,dword ptr [ebp-004h]
0040100D:   push      eax
0040100E:   mov       dword ptr [ebp-004h],00000001h
00401015:   mov       dword ptr [ebp-008h],00000002h
0040101C:   call      InitializeVariables
00401021:   pop       ecx
00401022:   mov       esi,dword ptr [_imp__wprintf]
00401028:   pop       ecx
00401029:   push      dword ptr [ebp-008h]
0040102C:   push      dword ptr [ebp-004h]
0040102F:   push      'string'
00401034:   call      esi
00401036:   add       esp,00Ch
00401039:   call      InitializeTLSValues
0040103E:   push      eax
0040103F:   push      'string'
00401044:   mov       dword ptr [ebp-004h],eax
00401047:   call      esi
00401049:   pop       ecx
0040104A:   pop       ecx
0040104B:   call      ReturnValue
00401050:   push      eax
00401051:   push      'string'
00401056:   mov       dword ptr [ebp-004h],eax
00401059:   call      esi
0040105B:   pop       ecx
0040105C:   pop       ecx
0040105D:   pop       esi
0040105E:   leave
0040105F:   ret
Figure 8 wmain Disassembly for Version 7.0
wmain:
00401000:   push      ebp
00401001:   mov       ebp,esp
00401003:   push      ecx
00401004:   push      ecx
00401005:   lea       eax,dword ptr [ebp-004h]
00401008:   push      esi
00401009:   push      eax
0040100A:   lea       eax,dword ptr [ebp-008h]
0040100D:   mov       dword ptr [ebp-008h],00000001h
00401014:   mov       dword ptr [ebp-004h],00000002h
0040101B:   call      InitializeVariables
00401020:   push      dword ptr [ebp-004h]
00401023:   mov       esi,dword ptr [_imp__wprintf]
00401029:   push      dword ptr [ebp-008h]
0040102C:   push      'string'
00401031:   call      esi
00401033:   call      InitializeTLSValues
00401038:   push      eax
00401039:   push      'string'
0040103E:   call      esi
00401040:   push      000000BBh
00401045:   push      'string'
0040104A:   call      esi
0040104C:   add       esp,020h
0040104F:   xor       eax,eax
00401051:   pop       esi
00401052:   leave
00401053:   ret
Show: