sehexcpt.c
来自「一本已经绝版的好书」· C语言 代码 · 共 260 行
C
260 行
/************************************************************
Module name: SEHExcpt.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
************************************************************/
#include "..\CmnHdr.H" /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h> // For sprintf
#include <stdlib.h> // For rand
#include "Resource.H"
/////////////////////////////////////////////////////////////
#define NUMELEMENTS (50)
// Declare each array element to be 4 KB.
typedef struct {
BYTE bReserved[4 * 1024];
} ELEMENT, *LPELEMENT;
/////////////////////////////////////////////////////////////
void CommitMemory (HWND hwndLog, LPEXCEPTION_POINTERS lpEP,
LPBYTE lpbAttemptedAddr) {
BOOL fAttemptedWrite;
TCHAR szBuf[100];
// Find out whether a memory access was tried.
fAttemptedWrite = (BOOL)
lpEP->ExceptionRecord->ExceptionInformation[0];
// Add an entry to the Execution Log list box.
_stprintf(szBuf,
__TEXT("---> Committing memory (%s attempted)"),
fAttemptedWrite ? __TEXT("write") : __TEXT("read"));
ListBox_AddString(hwndLog, szBuf);
// The attempted memory access did occur while the program
// was accessing an element in our array. Let's try to
// commit memory to an individual element of the reserved
// array's address space.
VirtualAlloc(lpbAttemptedAddr, sizeof(ELEMENT),
MEM_COMMIT, PAGE_READWRITE);
}
/////////////////////////////////////////////////////////////
int ExpFilter (LPEXCEPTION_POINTERS lpEP, LPBYTE lpbArray,
LONG lNumBytesInArray, HWND hwndLog) {
LPBYTE lpbAttemptedAddr = NULL;
// Get the exception code explaining
// why the filter is executing.
DWORD dwExceptionCode = lpEP->ExceptionRecord->ExceptionCode;
// Assume that this filter will NOT handle the exception
// and will let the system continue scanning
// for other filters.
int nFilterResult = EXCEPTION_CONTINUE_SEARCH;
__try {
// We must first determine whether the exception is
// occurring because of a memory access to our array of
// elements. This filter and handler do not process
// any other types of exceptions.
if (dwExceptionCode != EXCEPTION_ACCESS_VIOLATION) {
// If the exception is not a memory access violation,
// the exception doesn't come from an array element
// access. The system should continue its search for
// another exception filter.
nFilterResult = EXCEPTION_CONTINUE_SEARCH;
__leave;
}
if (lpbArray == NULL) {
// The exception occurred either before the program
// tried to reserve the address space or the
// array's address space was unsuccessfully reserved.
nFilterResult = EXCEPTION_CONTINUE_SEARCH;
__leave;
}
// Get the address of the attempted memory access.
lpbAttemptedAddr = (LPBYTE)
lpEP->ExceptionRecord->ExceptionInformation[1];
if ((lpbAttemptedAddr < lpbArray) ||
((lpbArray + lNumBytesInArray) < lpbAttemptedAddr)) {
// Address attempted is BELOW the beginning of the
// array's reserved space or is ABOVE the end of the
// array's reserved space. We'll let some other
// filter handle this exception.
nFilterResult = EXCEPTION_CONTINUE_SEARCH;
__leave;
}
// This filter will handle the exception.
CommitMemory(hwndLog, lpEP, lpbAttemptedAddr);
// Memory is committed now. Let's restart the
// instruction that caused the exception in the first
// place. This time, the instruction will succeed
// and not cause another exception.
nFilterResult = EXCEPTION_CONTINUE_EXECUTION;
}
__finally {
}
// Now that memory is committed, we can continue execution
// at the instruction that generated the exception in
// the first place.
return(nFilterResult);
}
/////////////////////////////////////////////////////////////
void Dlg_ReserveArrayAndAccessIt (HWND hwndLog,
int nNumAccesses) {
LPELEMENT lpArray = NULL;
ELEMENT Element;
TCHAR szBuf[100];
int nElementNum;
const LONG lNumBytesInArray = sizeof(ELEMENT) *
NUMELEMENTS;
// Clear the Execution Log list box.
ListBox_ResetContent(hwndLog);
ListBox_AddString(hwndLog, __TEXT("Execution started"));
__try {
// Reserve an address space large enough to
// hold NUMELEMENTS number of ELEMENTs.
lpArray = VirtualAlloc(NULL, lNumBytesInArray,
MEM_RESERVE, PAGE_NOACCESS);
while (nNumAccesses--) {
// Get the index of a random element to access.
nElementNum = rand() % NUMELEMENTS;
// Try a write access.
_stprintf(szBuf,
__TEXT("Writing index: %d"), nElementNum);
ListBox_AddString(hwndLog, szBuf);
// The exception will occur on this line.
lpArray[nElementNum] = Element;
} // while
// We have finished the execution.
ListBox_AddString(hwndLog, __TEXT("Execution ended"));
// Decommit and free the array of ELEMENTs.
VirtualFree(lpArray, 0, MEM_RELEASE);
} // __try
__except (
ExpFilter(GetExceptionInformation(), (LPBYTE) lpArray,
lNumBytesInArray, hwndLog)) {
// Because the filter never returns
// EXCEPTION_EXECUTE_HANDLER, there is nothing
// to do in the except block.
} // __except
}
/////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
// Associate an icon with the dialog box.
chSETDLGICONS(hwnd, IDI_SEHEXCPT, IDI_SEHEXCPT);
// Default the number of accesses to 100.
SetDlgItemInt(hwnd, IDC_NUMACCESSES, 100, FALSE);
return(TRUE);
}
/////////////////////////////////////////////////////////////
void Dlg_OnCommand (HWND hwnd, int id,
HWND hwndCtl, UINT codeNotify) {
int nNumAccesses;
BOOL fTranslated;
switch (id) {
case IDOK:
nNumAccesses = GetDlgItemInt(hwnd, IDC_NUMACCESSES,
&fTranslated, FALSE);
if (fTranslated) {
Dlg_ReserveArrayAndAccessIt(
GetDlgItem(hwnd, IDC_LOG), nNumAccesses);
} else {
chMB(__TEXT("Invalid number of accesses."));
}
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_SEHEXCPT),
NULL, Dlg_Proc);
return(0);
}
//////////////////////// End Of File ////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?