: , , Application Error, . , , , . , , , .
, Application Error, , , , , . , , , Dr. Watson, , , ? , , bug-tracking?
(crash handlers). , , (exception handlers), (unhandled exception filters). C++ . , , , (Application Error), . C++, Microsoft Visual C++, Microsoft Visual Basic.
, , . , , , . , 32- Microsoft (Win32).
(exeption handling) , C++ : (Structured Exception Handling SEH), , C++. , , , , . , . , , . . , , .
(SEH) . , . SEH- C/C++ _try/_except _try/_finally. _try/_except : _try, , _except ( (exception handler)). _try/_finally _finally ( (termination handler)) , ( _try/_except), _try .
9-1 SEH-. _except , , (exception filter). 9-1 (EXCEPTION_ EXECUTE_HANDLER) , except , try - () . EXCEPTION_CONTINUE_EXECUTION ( ) EXCEPTION_CONTINUE_SEARCH ( except). , , , .
9-1. SEH-
void Foo ( void) {
__try
{
_try
{
// ().
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
// , try
//
// . .
}
}
_finally
{
// ,
// .
// .
}
}
(unwinding the exception). . ( ) . , , , . "" , , . "" , Application Error.
GetExceptionCode, . , , , , " " NaN ( ). 9-2. GetExceptionCode, " ", . , EXCEPTION_CONTINUE_SEARCH , _except ( ).
9-2. SEH-
long IntegerDivide ( long x, long )
{
long IRet; _try
{
IRet = x / y;
}
_except ( EXCEPTION_INT_DIVIDE_BY_ZERO ==
GetExceptionCode ()
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTTNUE_SEARCH
)
{
IRet = NaN;
}
return ( IRet);
}
, ( , , ). GetExceptionCode, GetExceptionlnformation ( ). EXCEPTION_POINTERS, CPU . , EXCEPTION_POINTERS .
SEH- . API- RaiseException. , . RaiseException , setjmp longjmp ( ).
SEH- , . (): . : SEH- C++, C++- SEH-, . , SEH- , , . C++ (, ), .
, SEH- , ( MSDN). SEH- (Jeffrey Richter, Programming Applications for Microsoft Windows, Microsoft Press, 1999). SEH-, Matt Pietrek, "A Crash Course on the Depths of Win32 Structured Exception Handling" Microsoft Systems Journal 1997 .
C++, , , , SEH-. C++ try catch. throw . SEH- , catch C++ , . , . MFC (Microsoft Foundation Class) CException. 9-3 C++ MFC- CFiie.
9-3. ++
BOOL ReadFileHeader ( CFile * pFile, LPHEADERINFO pHeader)
{
ASSERT ( FALSE == IsBadReadPtr ( pFile, sizeof ( CFile *)));
ASSERT ( FALSE == IsBadReadPtr ( pHeader,
sizeof ( LPHEADERINFO)) ) ;
if ( ( TRUE == IsBadReadPtr ( pFile, sizeof ( CFile *))) ||
( TRUE = IsBadReadPtr ( pHeader,
Sizeof ( LPHEADERINFO) )) )
{
return ( FALSE) ;
}
BOOL bRet;
try ;
{
pFile->Read ( pHeader, sizeof ( HEADERINFO));
bRet = TRUE;
}
catch ( CFileException * e)
{
// - ,
// , ; ,
if ( CFileException:rendOfFile == e->m_cause)
{
e->Delete(); bRet = false;
}
else {
// throw ,
// catch-.
throw;
}
}
return ( bRet);
}
C++ . -, . ( .) -, C++ . , try catch, , , . , . C++, MSDN , .
, SEH- ++-. C++. _set_se_transiator C++ , , , C++. . , -:
void SEHToCPPException ( UINT uiEx,
EXCEPTION_POINTERS * pExp)
{
// CSEHException , MFC- CException
throw CSEHException ( uiEx, pExp);
}
SEH-, GetExceptionCode, GetExceptionlnformation.
_set_se_transiator , , . , DLL, DLL try.. .catch. , SEH-, . . , , .
, , SEH- C++, , . . , , . -, , EXCEPTION_STACK_OVERFLOW, , .
( SEH- C++), (), . ; , EXCEPTION_POINTERS . C++.
C++
C++ . , C++. C++ : , , , .
C++ , , . Visual C++ 5 . , "" . ( ).
, Visual C++ 6, , throw. , , "", throw. : " , , ".
, () _set_se_translator , , ( !). /GX /EHSC ( ), , , /a ( ). , .
( /a), , , _decispec(nothrow). , , _set_se_translator "" .
9-4 , _set_se_ translator, , (. . ) . /. , _set_se_transiator, , , / . ( , C++ MFC) , _set_se_transiator, (-) .
9-4. ,
// () Win32, /GX,
// , - .
// ( /GX /EHsc.)
// , /.
#include "stdafx.h"
class CSEHError
{
public :
CSEHError ( void)
{
m_uiErrCode = 0;
}
CSEHError ( unsigned int u)
{
m_uiErrCode = u;
}
~CSEHError ( void)
{
}
unsigned int m_uiErrCode;
};
void TransFunc ( unsigned int u, EXCEPTION_POINTERS * pEP)
{
printf ( "In TransFuncXn");
throw CSEHError ( u);
}
void GrungyFunc ( char * p)
{.
*P = 'p';
printf ( "This output should never be seen!\n");
}
void DoBadThings ( void)
{
try
{
GrungyFunc ( (char*)0xl);
}
catch ( CSEHError e)
{
printf ( "Got an exception! -> Ox%08X\n", e.m_uiErrCode);
}
}
int main ( int argc, char* argv[])
{
_set_se_translator ( TransFunc);
DoBadThings ();
return 0;
}
API- SetUnhandledExceptionFilter
C++ , , , , . , , , . , , Application Error , , Dr. Watson . , , , . , API- SetUnhandledExceptionFilter , . . , Win32 Microsoft Windows NT 3.5, . (1999) MSDN .
, . , , , , ( ), . . . !
, SetUnhandledExceptionFilter . (SetUnhandledExceptionFilter), , , , . , _except- . , : EXCEPTION_EXECUTE_HANDLER, EXCEPTION_CONTINUE_EXECUTION EXCEPTION_CONTINUE_SEARCH. - , , ++- _set_se_transiator, , . , , MFC. Visual Basic, , Visual Basic. , , - - , - ( , , , , ).
EXCEPTION_POINTERS. 9-5 , . , .
, setunhandiedExceptionFiiter. : , . . Q173652 Knowledge Base , . , C++ : SEH- . Baz CHJTESTS.CPP, , .
: , SetunhandiedExceptionFiiter, . ActiveX- , , . SetunhandiedExceptionFiiter; , .
BUGSLAYERUTIL.DLL CrashHandler API, . , , , . , . , , ( ), , . , CrashHandler API, . CrashHandler API 9-5.
9-5. CrashHandler.PP
/*- - - - - - - - - - - - - - - - - - - -
"Debugging Applications" (Microsoft Press)
Copyright () 1997-2000 John Robbing All rights reserved.
:
WORK_AROUND_SRCLINE_BUG
SymGetLineFromAddr; PDB-. DBGHELP.DLL, , IMAGEHLP.DLL.
- - - - - - - - - - - - - - - - - - - - - - - - -*/
#include "pch.h"
#include "BugslayerUtil.h"
#include "CrashHandler.h"
//
#include "Internal.h"
/*////////////////////////////////////
////////////////////////////////////////////////*
,
#define MAX_SYM_SIZE 256
#define BUFF_SIZE 1024
#define SYM_BUFF_SIZE 512
/*///////////////////////////////////////////////////
////////////////////////////////////////////////////*
// ( )
static PFNCHFILTFN g_pfnCallBack = NULL;
//
static LPTOP_LEVEL_EXCEPTION_FILTER g_pfnOrigFilt = NULL;
//
static HMODULE * g_ahMod = NULL;
// g_ahMod ( )
static UINT g_uiModCount = 0;
// , .
// ,
static TCHAR g_szBuff [ BUFF_SIZE ];
//
static BYTE g_stSymbol [ SYM_BUFF_SIZE ];
//
static IMAGEHLP_LINE g_stLine;
// ,
static STACKFRAME g_stFrame;
// , ,
static BOOL g_bSymEngInit = FALSE;
/*////////////////////////////////////////////////////
/////////////////////////////////////////////////////*/
//
LONG _stdcall CrashHandlerExceptionFilter ( EXCEPTION_POINTERS *
pExPtrs );
//
LPCTSTR ConvertSimpleException ( DWORD dwExcept);
// ,
LPCTSTR _stdcall
InternalGetStackTraceString ( DWORD dwOpts ,
EXCEPTION_POINTERS * pExPtrs);
// SymGetLineFromAddr
BOOL InternalSymGetLineFromAddr ( IN HANDLE hProcess ,
IN DWORD dwAddr ,
OUT PDWORD pdwDisplacement,
OUT PIMAGEHLP_LINE Line , );
// , void InitSymEng ( void);
// ,
void CleanupSymEng ( void);
/*/////////////////////////////////////////////////
//////////////////////////////////////////////////*/
// . MEMDUMPVALIDATOR.CPP .
// : initializers put in library initialization
// area ( )
#pragma warning (disable : 4073)
#pragma init_seg(lib)
class CleanUpCrashHandler
{
public :
CleanUpCrashHandler ( void)
{
}
--CleanUpCrashHandler ( void)
{
// ?
if ( NULL != g_ahMod)
{
VERIFY ( HeapFree ( GetProcessHeap (),
0
g_ahMod ));
g_ahMod = NULL;
}
if ( NULL != g_pfnOrigFilt)
{
/
// .
SetUnhandledExceptionFilter ( g_pfnOrigFilt);
}
}
};
//
static CleanUpCrashHandler g_cBeforeAndAfter;
/*/////////////////////////////////////////////////
////////////////////////////////////////////////*/
BOOL _stdcall SetCrashHandlerFilter ( PFNCHFILTFN pFn)
{
// NULL- "" .
if { NULL == pFn)
{
if ( NULL != g_pfnOrigFilt)
{
//
// .
SetUnhandledExceptionFilter ( g_pfnOrigFilt);
g_pfnOrigFilt = NULL;
if ( NULL ! = g_ahMod)
{
free ( g_ahMod);
g_ahMod = NULL;
}
g_pfnCallBack = NULL;
}
}
else
{
ASSERT ( FALSE == IsBadCodePtr ( (FARPROC)pFn));
if ( TRUE == IsBadCodePtr { (FARPROC)pFn))
{
return ( FALSE);
}
g_pfnCallBack = pFn;
// ,
// CrashHandlerExceptionFilter
// .
if ( NULL = = g_pfnOrigFilt)
{
g_pfnOrigFilt =
SetUnhandledExceptionFilter( CrashHandlerExceptionFilter);
}
}
return ( TRUE);
}
BOOL _stdcall AddCrashHandlerLimitModule ( HMODULE hMod)
{
//
ASSERT ( NULL != hMod);
if ( NULL == hMod)
{
return ( FALSE);
}_
// .
// , , // . ,
// , , ,
// .
HMODULE * phTemp = (HMODULE*)
HeapAlloc ( GetProcessHeap () ,
HEAP_ZERO_MEMORY |
HEAP_GENERATE_EXCEPTIONS ,
( sizeof ( HMODULE) * ( g_uiModCount+l)) );
ASSERT ( NULL != phTemp);
if ( NULL = phTemp)
{
TRACE0 ( "Serious trouble in the house! _ "
"HeapAlloc failed!!!\n" );
return ( FALSE);
}
if ( NULL = g_ahMod)
{
g_ahMod = phTemp;
g_ahMod[ 0 ] = hMod;
g_uiModCount++;
}
else
{
// .
CopyMemory ( phTemp ,
g_ahMod ,
sizeof ( HMODULE) * g_uiModCount) ;
// .
VERIFY ( HeapFree ( GetProcessHeap (), 0, g_ahMod));
g_ahMod = phTemp;
g_ahMod[ g_uiModCount ] = hMod;
g_uiModCount++;
}
return ( TRUE);
}
UINT _stdcall GetLimitModuleCount ( void)
{
return ( g_uiModCount);
}
int _stdcall GetLimitModulesArray ( HMODULE * pahMod, UINT uiSize)
{
int iRet;
_try
{
ASSERT ( FALSE == IsBadWritePtr ( pahMod,
uiSize * sizeof ( HMODULE)));
if ( TRUE == IsBadWritePtr ( pahMod,
uiSize * sizeof ( HMODULE)))
{
iRet = GLMA_BADPARAM;
_leave;
}.
if ( uiSize < g_uiModCount)
{
iRet = GLMA_BUFFTOOSMALL;
_leave;
}
CopyMemory ( pahMod ,
g_ahMod ,
sizeof ( HMODULE) * g_uiModCount);
iRet = GLMA_SUCCESS;
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
iRet = GLMA_FAILURE;
}
return ( iRet);
}
LONG _stdcall GrashHandlerExceptionFilter ( EXCEPTION_POINTERS* pExPtrs) {
LONG IRet = EXCEPTION_CONTINUE_SEARCH;
// EXCEPTION_STACK_OVERFLOW (
// ), ,
// . , , // .
// ,
// ,
// . , // , .
// // OutputDebugString. ,
// , OutputDebugString
// ( 8-16 ), .
//
// DebugView/Enterprise Edition
// (Mark Russinovich) www.sysinternals.com.
//
// , ,
// .
// , EXCEPTION_STACK_OVERFLOW .
// , .
// ,
// , .
if ( EXCEPTION_STACK_OVERFLOW ==
pExPtrs->ExceptionRecord->ExceptionCode)
{
OutputDebugString ( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
OutputDebugString ( "EXCEPTION_STACK_OVERFLOW occurred\n"); OutputDebugString ( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
_try
{
if ( NULL != g_pfnCallBack)
{
// ,
//
// ,
// .
InitSymEng ();
// g_ahMod.
BOOL bCalllt = FALSE;
if ( 0 == g_uiModCount)
{
bCalllt = TRUE;
}
else {
HINSTANCE hBaseAddr = (HINSTANCE)
SymGetModuleBase ((HANDLE)GetCurrentProcessId (), (DWORD)pExPtrs->
ExceptionRecord->
ExceptionAddress);
if ( NULL != hBaseAddr)
{
for ( UINT i = 0; i < g__uiModCount; i ++)
{
if ( hBaseAddr == g_ahMod[ i ])
{
bCalllt = TRUE; break;
}
}
}
}
if ( TRUE == bCalllt)
{
// ,
// .
// ,
// ,
// . , -
// , .
ASSERT ( FALSE == IsBadCodePtr( (FARPROC)g_pfnCallBack));
if ( FALSE == IsBadCodePtr ( (FARPROC)g_pfnCallBack))
{
IRet = g_pfnCallBack ( pExPtrs);
}
}
else
{
// , ,
// . !:)
ASSERT ( FALSE == IsBadCodePtr ( (FARPROC) g__pfnOrigFilt) ) ;
if ( FALSE == IsBadCodePtr ( (FARPROC)g_pfnOrigFiIt))
{
IRet = g_pfnOrigFilt ( pExPtrs);
}
}
CleanupSymEng ();
}
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
IRet = EXCEPTION_CONTINUE_SEARCH;
}
return ( IRet);
}
/*/////////////////////////////////////////////
- EXCEPTION_POINTER-yp
//////////////////////////////////////////////*/
LPCTSTR _stdcall GetFaultReason ( EXCEPTION_POINTERS * pExPtrs) {
ASSERT ( FALSE == IsBadReadPtr ( pExPtrs,
sizeof ( EXCEPTION_POINTERS)));
if ( TRUE = IsBadReadPtr ( pExPtrs,
sizeof ( EXCEPTION_POINTERS)))
{
TRACEO ( "Bad parameter to GetFaultReasonA\n");
return ( NULL);
}
// ,
LPCTSTR szRet;
_try
{
// ,
// .
InitSymEng ();
//
int iCurr = 0;
// .
// .
DWORD dwTemp;
iCurr += BSUGetModuleBaseName ( GetCurrentProcess (),
NULL
, g_szBuff ,
BUFF_SIZE );
iCurr += wsprintf ( g_szBuff + iCurr, _T ( " caused an "));
dwTemp = (DWORD)
ConvertSimpleException ( pExPtrs->ExceptionRecord->
ExceptionCode);
if ( NULL != dwTemp)
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( "%s") dwTemp );
}
else
{
iCurr += ( FormatMessage ( FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle (_T("NTDLL.DLL")),
pExPtrs->ExceptionRecord->
ExceptionCode,
0,
g_szBuff + iCurr ,
BUFF_SIZE,
0 )
* sizeof ( TCHAR));
}
ASSERT ( iCurr < ( BUFF_SIZE - MAX_PATH));
iCurr += wsprintf ( g_szBuff + i.Curr, _T ( " in module ") ) ;
dwTemp =
SymGetModuleBase ( (HANDLE)GetCurrentProcessId (),
(DWORD)pExPtrs->ExceptionRecord->
ExceptionAddress);
ASSERT ( NULL != dwTemp);
if ( NULL == dwTemp)
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( "<UNKNOWN>"));
}
else
{
iCurr += BSUGetModuleBaseName ( GetCurrentProcess () ,
(HINSTANCE)dwTemp ,
g_szBuff + iCurr
BUFF_SIZE - iCurr );
}
#ifdef _WIN64
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( " at %016X") ,
pExPtrs->ExceptionRecord->ExceptionAddress);
#else
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( " at %04X:%08X") ,
pExPtrs->ContextRecord->SegCs ,
pExPtrs->ExceptionRecord->ExceptionAddress);
#endif
ASSERT ( iCurr < ( BUFF_SIZE _ 200));
// .
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&g_stSymbol;
FillMemory ( pSym, NULL, SYM_BUFF_SIZE);
pSym->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL);
pSym->MaxNameLength = SYM_BUFF_SIZE - sizeof ( IMAGEHLP_SYMBOL);
DWORD dwDisp;
if ( TRUE ==
SymGetSymFromAddr ( (HANDLE)GetCurrentProcessId () ,
(DWORD)pExPtrs->ExceptionRecord->
ExceptionAddress ,
SdwDisp ,
pSym ) )
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( ", "));
// ,
// .
dwTemp = Istrlen ( pSym->Name);
// ,
// .
if ( (int)dwTemp > ( ( BUFF_SIZE _ iCurr) -
( MAX_SYM_SIZE +50) ))
{
Istrcpyn ( g_szBuff + iCurr ,
pSym->Name ,
BUFF_SIZE - iCurr - 1 );
//
szRet = g_szBuff; _leave;
}
else
{
if ( dwDisp > 0)
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( "%s()+%04d byte(s)"),
pSym->Name ,
dwDisp );
}
else
{
iCurr += wsprintf ( g_szBuff + iCurr,
_T ( "%s ") pSym->Name ) ;
}
}
}
else
{
// ,
// , .
szRet = g_szBuff;
_leave;
}
ASSERT ( iCurr < ( BUFF_SIZE _ 200));
// .
ZeroMemory ( &g_stLine, sizeof ( IMAGEHLP_LINE));
g_stLine.SizeOfStruct = sizeof ( IMAGEHLP_LINE);
if ( TRUE ==
InternalSymGetLineFromAddr ( (HANDLE)
GetCurrentProcessId () ,
(DWORD)pExPtrs->
ExceptionRecord->
ExceptionAddress,
SdwDisp ,
&g_stLine ))
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( ", "));
//
// , .
dwTemp = Istrlen ( g_stLine.FileName);
if ( (int)dwTemp > ( BUFF_SIZE - iCurr
_ MAX_PATH _ 50 ))
{
Istrcpyn ( g_szBuff + iCurr ,
g_stLine.FileName ,
BUFF_SIZE - iCurr - 1);
//
szRet = g_szBuff;
_leave;
}
else
{
if ( dwDisp > 0)
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T("%s, line %04d+%04d byte(s)"),
g_stLine.FileName ,
g_stLine. LineNumber ,
dwDisp ) ;
}
else
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( "%s, line %04d"),
g_stLine.FileName ,
g_stLine.LineNumber);
}
}
}
szRet = g_szBuff;
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
ASSERT ( !"Crashed in GetFaultReason");
szRet = NULL;
}
return ( szRet);
}
BOOL _stdcall GetFaultReasonVB ( EXCEPTION_POINTERS * pExPtrs,
LPTSTR szBuff , UINT uiSize )
{
ASSERT ( FALSE == IsBadWritePtr ( szBuff, uiSize));
if ( TRUE == IsBadWritePtr ( szBuff, uiSize))
{
return ( FALSE);
}
LPCTSTR szRet;
__try
{
szRet = GetFaultReason ( pExPtrs);
ASSERT ( NULL != szRet);
if ( NULL == szRet)
{
_leave;
}
Istrcpyn ( szBuff ,
szRet ,
min ( (UINT)Istrlen ( szRet) + 1, uiSize));
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
szRet = NULL;
}
return ( NULL != szRet);
}
LPCTSTR BUGSUTIL_DLLINTERFACE _stdcall
GetFirstStackTraceString ( DWORD dwOpts ,
EXCEPTION_POINTERS * pExPtrs)
{
//
// InternalGetStackTraceString
// STACKFRAME .
ZeroMemory ( &g_stFrame, sizeof ( STACKFRAME));
#ifdef _X86_
g_stFrame.AddrPC.Offset = pExPtrs->ContextRecord->Eip;
g_stFrame.AddrPC.Mode = AddrModeFlat ;
g_stFrame.AddrStack.Offset = pExPtrs->ContextRecord->Esp;
g_stFrame.AddrStack.Mode = AddrModeFlat ;
g_stFrame.AddrFrame.Offset = pExPtrs->ContextRecord->Ebp;
g_stFrame.AddrFrame.Mode = AddrModeFlat ;
#else
g_stFrame.AddrPC.Offset = (DWORD)pExPtrs->ContextRecord->Fir;
g_stFrame.AddrPC.Mode = AddrModeFlat;
g_stFrame.AddrReturn.Offset =
(DWORD)pExPtrs->ContextRecord->IntRa;
g_stFrame.AddrReturn.Mode = AddrModeFlat;
g_stFrame.AddrStack.Offset =
(DWORD)pExPtrs->ContextRecord->IntSp;
g_stFrame.AddrStack.Mode = AddrModeFlat;
g_stFrame.AddrFrame.Offset -
(DWORD)pExPtrs->ContextRecord->IntFp;
g_stFrame.AddrFrame.Mode = AddrModeFlat;
#endif
return ( InternalGetStackTraceString ( dwOpts, pExPtrs));
}
LPCTSTR BUGSUTIL_DLLINTERFACE _stdcall
GetNextStackTraceString ( DWORD dwOpts ,
EXCEPTION_POINTERS * pExPtrs)
{
// InternalGetStackTraceString.
// , GetFirstStackTraceString
// ,
return ( InternalGetStackTraceString ( dwOpts, pExPtrs));
}
BOOL _stdcall CH__ReadProcessMemory ( HANDLE ,
LPCVOID IpBaseAddress ,
LPVOID IpBuffer ,
DWORD nSize ,
LPDWORD IpNumberOfBytesRead )
{
return ( ReadProcessMemory ( GetCurrentProcess (),
IpBaseAddress ,
IpBuffer ,
nSize ,
IpNumberOfBytesRead ));
}
// ,
LPCTSTR _stdcall
InternalGetStackTraceString ( DWORD dwOpts ,
EXCEPTION_POINTERS * pExPtrs )
{
ASSERT ( FALSE == IsBadReadPtr ( pExPtrs
sizeof ( EXCEPTION_POINTERS)));
if ( TRUE == IsBadReadPtr ( pExPtrs ,
sizeof ( EXCEPTION_POINTERS)))
{
TRACED ( "GetStackTraceString invalid pExPtrs!\n");
return ( NULL);
}
// LPCTSTR szRet;
// .
// . DWORD dwTemp;
// .
// , , .
DWORD dwModBase;
_try
{
// ,
// .
InitSymEng ();
#ifdef _WIN64
#define CH_MACHINE IMAGE_FILE_MACHINE_IA64
#else
#define CH_MACHINE IMAGE_FILE_MACHINE_I386
#endif
// :
// , StackWalk
// .
BOOL bSWRet = StackWalk ( CH_MACHINE ,
(HANDLE)GetCurrentProcessId () ,
GetCurrentThread () ,
&g_stFrame ,
pExPtrs->ContextRecord ,
(PREAD_PROCESS_MEMORY_ROUTINE)
CH_ReadProcessMemory ,
SymFunctionTableAccess ,
SymGetModuleBase ,
NULL ) ;
if ( ( FALSE = bSWKet) 11(0= g_stFrame.AddrFrame.Offset))
{
szRet = NULL;
_leave;
}
// ,
// , ,
// StackWalk, . ,
// StackWalk, TRUE,
// .
dwModBase = SymGetModuleBase ( (HANDLE)GetCurrentProcessId (),
g_stFrame.AddrPC.Offset );
if ( 0 == dwModBase)
{
szRet = NULL;
_leave;
}
int iCurr = 0;
// ,
#ifdef _WIN64
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( "Ox%016X") ,
g_stFrame.AddrPC.Offset );
#else
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( "%04X:%08X")
pExPtrs->ContextReeord->SegCs, g_stFrame.AddrPC.Offset );
#endif
// ?
if ( GSTSO_PARAMS == ( dwOpts & GSTSO_PARAMS))
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( " ( Ox%08X Ox%08X "\
"Ox%08X Ox%08X)"),
g_stFrame.Params[ 0 ] ,
g_stFrame.Params[ 1 ] ,
g_stFrame.Params[ 2 ] ,
g_stFrame.Params[ 3 ] );
}
// .
if ( GSTSO_MODULE = ( dwOpts & GSTSO_MODULE))
{
iCurr += wsprintf ( g_szBuff + iCurr , _T ( " "));
ASSERT ( iCurr < ( BUFF_SIZE - MAX_PATH));
iCurr += BSUGetModuleBaseName ( GetCurrentProcess (),
(HINSTANCE)dwModBase,
g_szBuff + iCurr ,
BUFF_SIZE - iCurr );
}
ASSERT ( iCurr < ( BUFF_SIZE - MAX_PATH));
DWORD dwDisp;
// ?
if ( GSTSO_SYMBOL == ( dwOpts & GSTSO_SYMBOL))
{
// .
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)Sg_stSymbol;
ZeroMemory ( pSym, SYM_BUFF_SIZE);
pSym->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL);
pSym->MaxNameLength = SYM_BUFF_SIZE -
sizeof ( IMAGEHLP_SYMBOL);
if ( TRUE ==
SymGetSymFromAddr ( (HANDLE)GetCurrentProcessId () ,
g_stFrame.AddrPC.Offset ,
sdwDisp ,
pSym ))
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( ", "));
// ,
// .
dwTeitip = Istrlen ( pSym->Name) ;
if ( dwTeitip > (DWORD) ( BUFF_SIZE - iCurr _
( MAX_SYM_SIZE + 50)))
{
Istrcpyn ( g_szBuff + iCurr ,
pSym->Name ,
BUFF_SIZE - iCurr - 1 );
//
szRet = g_szBuff;
_leave;
}
else
{
if ( dwDisp > 0)
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T( "%s()+%04d byte(s)"),
pSym->Name ,
dwDisp ) ;
}
else
{
iCurr += wsprintf ( g_szBuff + iCurr,
_T ( "%s")
pSym->Name ) ;
}
}
}
else
{
// ,
// , .
szRet = g_szBuff;
_leave;
}
}
ASSERT ( iCurr < ( BUFF_SIZE - MAX_PATH));
// ?
if ( GSTSO_SRCLINE == ( dwOpts & GSTSO_SRCLINE))
{
ZeroMemory ( &g_stLine, sizeof ( IMAGEHLP_LINE));
g_stLine.SizeOfStruct = sizeof ( IMAGEHLP_LINE);
if ( TRUE ==
InternalSymGetLineFromAddr ( (HANDLE)
GetCurrentProcessId (),
g_stFrame.AddrPC.Offset ,
SdwDisp ,
&g_stLine ))
{
iCurr += wsprintf ( g_szBuff + iCurr, _T ( ", "));
//
// , .
dwTemp = Istrlen ( g_stLine.FileName);
if ( dwTerap > (DWORD)( BUFF_SIZE - iCurr
_ ( MAX_PATH +50 ))) {
Istrcpyn ( g_szBuff + iCurr ,
g_stLine.FileName ,
BUFF_SIZE - iCurr - 1 );
//
szRet = g_szBuff;
_leave;
}
else
{
if { dwDisp > 0)
{
iCurr += wsprintf(g_szBuff + iCurr ,
_T("%s, line %04d+%04d byte(s)"),
g_stLine.FileName ,
g_s tLine.LineNumbe r ,
dwDisp ) ;
}
else
{
iCurr += wsprintf ( g_szBuff + iCurr ,
_T ( "%s, line %04d") ,
g_stLine.FileName ,
g_stLine.LineNumber );
}
}
}
}
szRet = g_szBuff;
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
ASSERT ( !"Crashed in InternalGetStackTraceString");
szRet = NULL;
}
return ( szRet);
}
BOOL _stdcall
GetFirstStackTraceStringVB ( DWORD dwOpts ,
EXCEPTION_POINTERS * pExPtrs,
LPTSTR szBuff ,
UINT uiSize )
{
ASSERT ( FALSE == IsBadWritePtr ( szBuff, uiSize));
if ( TRUE = IsBadWritePtr ( szBuff, uiSize))
{
return ( FALSE);
}
LPCTSTR szRet;
_try
{
szRet = GetNextStackTraceString ( dwOpts, pExPtrs);
if ( NULL == szRet)
{
_leave;
}
Istrcpyn ( szBuff , szRet ,
min ( (UINT)lstrlen ( szRet) + I, uiSize));
}
_except ( EXCEPTION_EXECUTE_HANDLER)
{
szRet = NULL;
}
return ( NULL != szRet);
}
LPCTSTR _stdcall GetRegisterString ( EXCEPTION_POINTERS * pExPtrs) {
// .
ASSERT ( FALSE = IsBadReadPtr ( pExPtrs ,
sizeof ( EXCEPTION_POINTERS)));
if { TRUE = IsBadReadPtr ( pExPtrs ,
sizeof ( EXCEPTION_POINTERS)))
{
TRACED ( "GetRegisterString - invalid pExPtrs!\n");
return ( NULL);
}
#ifdef _WIN64
ASSERT ( !"IA64 is not supported (YET!) ");
#else
// 48 , ,
// ,
wsprintf ( g_szBuff,
_ ( "=%08 =%08 =%08 EDX=%08X ESI=%08X\n"\
"EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"\
"CS=%04X DS=%04X SS=%04X ES=%04X "\
"FS=%04X GS=%04X"),
pExPtrs->ContextRecord->Eax ,
pExPtrs->ContextRecord->Ebx ,
pExPtrs->ContextRecord->Ecx ,
pExPtrs->ContextRecord->Edx ,
pExPtrs->ContextRecord->Esi ,
pExPtrs->ContextRecord->Edi ,
pExPtrs->ContextRecord->Ebp ,
pExPtrs->ContextRecord->Esp ,
pExPtrs->ContextRecord->Eip ,
pExPtrs->ContextRecord->EFlags ,
pExPtrs->ContextRecord->SegCs ,
pExPtrs->ContextRecord->SegDs ,
pExPtrs->ContextRecord->SegSs ,
pExPtrs->ContextRecord->SegEs ,
pExPtrs->ContextRecord->SegFs ,
pExPtrs->ContextRecord->SegGs );
#endif
return ( g_szBuff);
}
BOOL _stdcall GetRegisterStringVB ( EXCEPTION_POINTERS * pExPtrs,
LPTSTR szBuff , UINT uiSize )
{
ASSERT ( FALSE == IsBadWritePtr ( szBuff, uiSize));
if ( TRUE == IsBadWritePtr ( szBuff, uiSize))
{
return ( FALSE);
}
LPCTSTR szRet;
_try
{
szRet = GetRegisterString ( pExPtrs);
if ( NULL = szRet)
{
_leave;
}
Istrcpyn ( szBuff , szRet ,
min ( (UINT)Istrlen ( szRet) + 1, uiSize));
}
_except ( EXCEPTION_EXECUTE_HANDLER) {
szRet = NULL;
}
return ( NULL != szRet);
}
LPCTSTR ConvertSimpleException ( DWORD dwExcept)
{
switch ( dwExcept)
{
case EXCEPTION_ACCESS_VIOLATION :
return ( _T ( "EXCEPTION_ACCESS_VIOLATION"));
break;
case EXCEPTION_DATATYPE_MISALIGNMENT :
return ( _T ( "EXCEPTION_DATATYPE_MISALIGNMENT"));
break;
case EXCEPTION_BREAKPOINT :
return ( _T ( "EXCEPTION_BREAKPOINT"));
break;
case EXCEPTION_SINGLE_STEP :
return ( _T ( "EXCEPTION_SINGLE_STEP"));
break;
case EXCEPTION_ARRAY_BOUNDSJEXCEEDED
return ( _T ( "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
break;
case EXCEPTION_FLT_DENORMAL_OPERAND :
return ( _T ( "EXCEPTION_FLT_DENORMAL_OPERAND"));
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO :
return ( _T ( "EXCEPTION_FLT_DIVIDE_BY_ZERO"));
break;
case EXCEPTION_FLT_INEXACT_RESULT :
return ( _T ( "EXCEPTION_FLT_INEXACT_RESULT"));
break;
case EXCEPTION_FLT_INVALID_OPERATION :
return ( _T ( "EXCEPTION_FLT_INVALID_OPERATION"));
break;
case EXCEPTION_FLT_OVERFLOW :
return ( _T ( "EXCEPTION_FLT_OVERFLOW"));
break;
case EXCEPTION_FLT_STACK_CHECK :
return ( _T ( "EXCEPTION_FLT_STACK_CHECK"));
break;
case EXCEPTION_FLT_UNDERFLOW :
return ( _T ( "EXCEPTION_FLT_UNDERFLOW")); break; case EXCEPTION_INT_DIVIDE_BY_ZERO :
return ( _T ( "EXCEPTION_INT_DIVIDE_BY_ZERO"));
break;
case EXCEPTION_INT_OVERFLOW :
return ( _T ( "EXCEPTION_INT_OVERFLOW"));
break;
case EXCEPTION_PRIV_INSTRUCTION :
return ( _T ( "EXCEPTION_PRIV_INSTRUCTION"));
break;
case EXCEPTION_IN_PAGE_ERROR :
return ( _T ( "EXCEPTION_IN_PAGE_ERROR"));
break;
case EXCEPTION_ILLEGAL_INSTRUCTION :
return ( _T ( "EXCEPTION_ILLEGAL_INSTRUCTION"));
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION :
return ( _T ( "EXCEPTION_NONCONTINUABLE_EXCEPTION")); break;
case EXCEPTION_STACK_OVERFLOW :
return ( _T ( "EXCEPTION_STACK_OVERFLOW"));
break;
case EXCEPTION_INVALID_DISPOSITION :
return ( _T ( "EXCEPTION_INVALID_DISPOSITION"));
break;
case EXCEPTION_GUARD_PAGE :
return ( _T ( "EXCEPTION_GUARD_PAGE"));
break;
case EXCEPTION_INVALID_HANDLE :
return ( _T ( "EXCEPTION_INVALID_HANDLE"));
break;
default :
return ( NULL);
break;
}
}
BOOL InternalSymGetLineFromAddr ( IN HANDLE hProcess ,
IN DWORD dwAddr ,
OUT PDWORD pdwDisplacement,
OUT PIMAGEHLP_LINE Line )
{
#ifdef WORK_AROUND_SRCLINE_BUG
// ,
// ( ),
// . 100 ,
// , .
DWORD dwTempDis = 0;
while ( FALSE == SymGetLineFromAddr ( hProcess ,
dwAddr -
dwTempDis ,
pdwDisplacement,
Line ) )
{
dwTempDis += 1;
if ( 100 == dwTempDis)
{
return ( FALSE);
}
}
// ,
// ,
// , ,
if ( 0 != dwTempDis)
{
*pdwDisplacement = dwTempDis;
}
return ( TRUE);
#else // WORK_AROUND_SRCLINE_BUG
return ( SymGetLineFromAddr ( hProcess ,
dwAddr ,
pdwDisplacement ,
Line ));
#endif
}
// ,
void InitSymEng ( void)
{
if ( FALSE == g_bSymEngInit)
{
// .
DWORD dwOpts = SymGetOptions ();
// .
SymSetOptions ( dwOpts |
SYMOPT_DEFERRED_LOADS |
SYMOPT_LOAD_LINES );
// ,
// , .
HANDLE hPID = (HANDLE)GetCurrentProcessId ();
VERIFY ( BSUSymlnitialize ( (DWORD)hPID,
hPID ,
NULL ,
TRUE ));
g_bSymEngInit = TRUE;
}
}
// , ,
void CleanupSymEng ( void) CrashHandler
{
if ( TRUE == g_bSymEngInit)
{
VERIFY ( SymCleanup ( (HANDLE)GetCurrentProcessId ()));
g_bSymEngInit = FALSE;
}
}
, SetCrashHandierFiiter, SetUnhandledExceptionFilter, CrashHandlerExceptionFilter. - , , CrashHandlerExceptionFilter , , . , , , , API-. SetCrashHandierFiiter , NULL- , .
AddCrashHandierLimitModuie , , . , ( HMODULE hMod). , AddCrashHandierLimitModuie . .
9-5, , - (run-time) C++. , , . , , , BUGSLAYERUTIL.DLL . GetLimitModuleCount GetLimitModulesArray, . RemoveCrashHandlerLimitModule .
CRASHHANDLER.CPP DBGHELP.DLL. , , . Syminitiaiize, (finvadeProcess) TRUE. , Windows 2000, Windows 98. Windows 98, Bsusyminitialize BUGSLAYERUTIL.DLL, .
, EXCEPTION_POINTERS, . , , , . ( ). 9-5.
, . , EXCEPTION_POINTERS. , . , , "", "VB1". , VB- , -. , EXCEPTION_POINTERS , , . , , Visual Basic , . -, - , . Visual Basic , .
Visual Basic. .
GetRegisterString . GetFauitReason , . , , , , , , , :
CH_TESTS.EXE caused an EXCEPTION_ACCESS_VIOLATION in module CH_TESTS.EXE at 001B:004010FB, Baz()+0064 bytes, CHJTests.cpp, line 0060+0003 bytes
GetFirstStackTraceString GetNextstackTracestring. , . API- FindFirstFiie FindNextFile, GetFirstStackTraceString , GetNextstackTracestring , FALSE. EXCEPTION_POINTERS, , , . , () :
001:004018 (0x00000001 Ox008COF90 Ox008C0200 Ox77F8FE94) CH_TESTS.EXE, main()+1857 bytes, CHJTests., line 0341+0007 bytes
. . 9.1 .
9.1. GetFirststackTraceString GetNextStackTraceString
0
GSTSO_PARAMS
GSTSO MODULE
GSTSO SYMBOL
GSTSO_SRCLINE
. 9.1. CrashTest
, CD . , CH_TEST, C/C++, , CrashTest, Visual Basic. , . . 9.1 CrashTest .
, . . Visual C++, Visual Basic, Visual C++.
C++- SEH-. C++, SEH- . . , C++- SHE- _set_se_translator C++. , C++. : " , , ".
SetunhandiedExceptionFiiter, SEH- . , Application Error, . (CrashHandler) , .
10.11.2021 - 12:37: - Personalias -> WHO IS WHO - - _. 10.11.2021 - 12:36: - Conscience -> . ? - _. 10.11.2021 - 12:36: , , - Upbringing, Inlightening, Education -> ... - _. 10.11.2021 - 12:35: - Ecology -> - _. 10.11.2021 - 12:34: , - War, Politics and Science -> - _. 10.11.2021 - 12:34: , - War, Politics and Science -> . - _. 10.11.2021 - 12:34: , , - Upbringing, Inlightening, Education -> , - _. 10.11.2021 - 09:18: - New Technologies -> , 5G- - _. 10.11.2021 - 09:18: - Ecology -> - _. 10.11.2021 - 09:16: - Ecology -> - _. 10.11.2021 - 09:15: , , - Upbringing, Inlightening, Education -> - _. 10.11.2021 - 09:13: , , - Upbringing, Inlightening, Education -> - _. |