sehsum.c

来自「一本已经绝版的好书」· C语言 代码 · 共 189 行

C
189
字号
/*************************************************************
Module name: SEHSum.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
*************************************************************/


#include "..\CmnHdr.H"                  /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <limits.h>
#include <process.h>           // For _beginthreadex
#include <tchar.h>
#include "Resource.H"


/////////////////////////////////////////////////////////////


// An example of calling Sum for uNum = 0 through 9
// uNum: 0 1 2 3  4  5  6  7  8  9 ...
// Sum:  0 1 3 6 10 15 21 28 36 45 ...
UINT Sum (UINT uNum) {

   if (uNum == 0) 
      return(0);

   // Call Sum recursively.
   return(uNum + Sum(uNum - 1));
}


/////////////////////////////////////////////////////////////


long FilterFunc (DWORD dwExceptionCode) {

   // Assume that we do not know how to handle the exception;
   // tell the system to continue to search for an SEH
   // handler.
   long lRet = EXCEPTION_CONTINUE_SEARCH;

   if (dwExceptionCode == STATUS_STACK_OVERFLOW) {
      // If the exception raised is a stack overflow,
      // we do know how to handle it.
      lRet = EXCEPTION_EXECUTE_HANDLER;
   }

   return(lRet);
}


/////////////////////////////////////////////////////////////


// The separate thread that is responsible for calculating the
// sum. I use a separate thread for the following reasons:
// 1. A separate thread gets its own 1 MB of stack space.
// 2. A thread can be notified of a stack overflow only once.
// 3. The stack's storage is freed when the thread exits.
DWORD WINAPI SumThreadFunc (PVOID p) {

   // The parameter, p, is really a UINT containing 
   // the number of integers to sum.
   UINT uSumNum = (UINT) p;

   // uSum contains the summation of the numbers
   // from 0 through uSumNum. If the sum cannot be calculated,
   // a sum of UINT_MAX is returned.
   UINT uSum = UINT_MAX;

   __try {
      // To catch the stack overflow exception, we must 
      // execute the Sum function while inside an SEH block.
      uSum = Sum(uSumNum); 
   }
   __except (FilterFunc(GetExceptionCode())) {
      // If we get in here, it's because we have trapped
      // a stack overflow. We can now do whatever is 
      // necessary to gracefully continue execution.
      // This sample application has nothing to do, so
      // no code is placed in this exception handler block.
   }

   // The thread's exit code is the sum of the first uSumNum 
   // numbers, or UINT_MAX if a stack overflow occurred.
   return(uSum);
}


/////////////////////////////////////////////////////////////


BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus, 
   LPARAM lParam) {

   // Associate an icon with the dialog box.
   chSETDLGICONS(hwnd, IDI_SEHSUM, IDI_SEHSUM);

   return(TRUE);
}


/////////////////////////////////////////////////////////////


void Dlg_OnCommand (HWND hwnd, int id, 
   HWND hwndCtl, UINT codeNotify) {

   UINT uSumNum, uSum;
   BOOL fTranslated;
   DWORD dwThreadId;
   HANDLE hThread;
      
   switch (id) {
      case IDC_CALC:
         // Get the number of integers the user wants to sum.
         uSumNum = GetDlgItemInt(hwnd, IDC_SUMNUM,
            &fTranslated, FALSE);

         // Create a thread (with its own stack) that is
         // responsible for performing the summation.
         hThread = chBEGINTHREADEX(NULL, 0, SumThreadFunc, 
               (PVOID) uSumNum, 0, &dwThreadId);

         // The thread's exit code is the resulting summation.
         
         // We must first wait for the thread to terminate.
         WaitForSingleObject(hThread, INFINITE);

         // Now we can get the thread's exit code.
         GetExitCodeThread(hThread, (PDWORD) &uSum);

         // Finally, we close the handle to the thread so
         // that the system can destroy the thread object.
         CloseHandle(hThread);

         // Update the dialog box to show the result.
         if (uSum == UINT_MAX) {
            // If the thread's exit code is UINT_MAX, a stack 
            // overflow occurred.  Update the dialog box 
            // and display a message box.
            SetDlgItemText(hwnd, IDC_ANSWER, __TEXT("Error"));
            chMB(__TEXT("The number is too big, ")
               __TEXT("please enter a smaller number"));
         } else {
            // The sum was calculated successfully; 
            // update the dialog box.
            SetDlgItemInt(hwnd, IDC_ANSWER, uSum, FALSE);
         }

         break;
        
      case IDCANCEL:
         EndDialog(hwnd, id);
         break;
   }
}

/////////////////////////////////////////////////////////////


BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, 
   WPARAM wParam, LPARAM lParam) {

   switch (uMsg) {
      chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
      chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
   }

   return(FALSE);
}


/////////////////////////////////////////////////////////////


int WINAPI _tWinMain (HINSTANCE hinstExe,
   HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {

   chWARNIFUNICODEUNDERWIN95();
   DialogBox(hinstExe, MAKEINTRESOURCE(IDD_SUMMATION), 
      NULL, Dlg_Proc);

   return(0);
}


//////////////////////// End Of File ////////////////////////

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?