NT的结构化异常处理1

先锋7号
NT的异常处理机制1
作者:杨历
注意这里说的是NT的异常处理。不是C++的异常处理,尽管他们非常类似。
NT异常处理的相关关键字是__try , __except , __finally , __leave. (注意有下划线)
他是由操作系统和编译器共同实现的。
C++异常处理的相关关键字是try , catch , ...我将在晚些时候向大家介绍。
他是编译器实现的功能。
1) 终止处理语句:
__try
{
// Guarded body
}
__finally
{
// Termintion handler
}
在上面的代码段中,操作系统和编译器保证程序一旦进入__try块,就一定会执行__finally块。
不管__try块是如何退出的。使用return , goto , 甚至 longjump __finally块都会执行。
例子:
int FunctionX( void )
{
int iTemp;
// Do any processing here.
__try{
WaitForSingleObject(g_hSem , INFINITE );
iTemp = 5;
return iTemp; // return function here.
}
__finally
{
ReleaseSemaphore( g_hSem , 1 , NULL );
}
dwTemp = 9;
return dwTemp;
}
这里程序返回的是5,而不是9。函数的__finally在函数返回前释放了信号量。
自己练习一下:
VC6下创建一个Win32应用程序。使用F10跟踪一下。
(我跟踪一半之后断了,但是执行结果是对的)
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
int iTemp = 0;
while ( iTemp < 10 )
{
__try
{
if ( iTemp == 2 ) continue;
if ( iTemp == 3 ) break;
}
__finally { iTemp ++ ;}
// __finally iTemp++ ; 不能过编译。
iTemp ++;
}
char szTemp[10];
sprintf( szTemp , "%d " , iTemp );
::MessageBox( 0 , szTemp , "结果" , MB_ICONINFORMATION | MB_OK );
return 0;
}
(显示结果应该是 4 );
使用__leave的例子:
DWORD FunctionY( void )
{
HANDLE hFile = INVALID_HANDLE_VALUE;
LPVOID lpBuf = NULL;
__try
{
DWORD dwNumByteRead;
BOOL fOK;
hFile = CreateFile("SOMEDATA.DAT" , ... );
if ( hFile == INALID_HANDLE_VALUE) __leave; //<<===
lpBuf = VirtualAlloc ( NULL , 1024 , ... );
if (lpBuf == NULL ) __leave; //<<===
fOK = ReadFile( hFIle , hpBuf , 1024 ,... );
if (!(fOK || (dwNumBytesRead == 0) __leave ;//<<===
// DO some calculation on the data.
fFunctionOK = TRUE;
}
__finally
{
if (lpBUf != NULL )
VirtualFree(lpBuf , MEM_RELEASE| MEM_DECOMMIT );
if ( hFile != INVALID_HANDLE_VALUE )
CloseHandle( hFile );
}
// Contiune processing.
return ( fFucntionOK);
}
在__try块中使用__leave关键字导致了向try块的末尾的一个跳转。控制流转向finally块。
有空在和大家一起学习。

当我离开西北工业大学后,才发现这里原来也是一所好大学