重写Funcaram1函数,其代码如清单八。
BOOL Funcarama3 (void) {
HANDLE hFile = INVALID_HANDLE_VALUE;
LPVOID lpBuf = NULL;
__try {
DWORD dwNumBytesRead;
BOOL fOk;
hFile = CreateFile("SOMEDATA.DAT", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return (FALSE);
}
lpBuf = VitualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (lpBuf == NULL) {
return (FALSE);
}
fOk = ReadFile(hFile, lpBuf, 1024, &dwNumBytesRead, NULL);
if (!fOk || (dwNumBytesRead == 0)) {
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
return (FALSE);
}
// Do some calculation on the data.
.
.
.
}
__finally {
// Clean up all the resources.
if (lpBuf != NULL)
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
// Continue processing.
return (TRUE);
}
例8 使用了中断处理句柄的Funcarama3函数代码
Funcarama3函数版的好处是所有的清除工作都集中在一个地方:finally程序段内。这样在我们需要对该函数增加新的条件语句时,我们只需要在finally程序段内简单增添一行清除语句就可以了,而不必回过头来在每一出可能出错的地方添加清除语句。
Funcarama3函数的真正问题在于其效率。我们以前说过应尽可能的避免在try程序段内使用return语句。为了避免这种情况,微软在它的编译器里引进了另一个关键词__leave。利用关键词__leave重写的Funcarama3函数见例9。
BOOL Funcarama4 (void) {
HANDLE hFile = INVALID_HANDLE_VALUE;
LPVOID lpBuf = NULL;
// Assume that the function will not execute successfully.
BOOL fFunctionOk = FALSE;
__try {
DWORD dwNumBytesRead;
BOOL fOk;
hFile = CreateFile("SOMEDATA.DAT", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
__leave;
}
lpBuf = VitualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (lpBuf == NULL) {
__leave;
}
fOk = ReadFile(hFile, lpBuf, 1024, &dwNumBytesRead, NULL);
if (!fOk || (dwNumBytesRead == 0)) {
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
__leave;
}
// Do some calculation on the data.
.
.
.
// Indicate that the entire function executed successfully.
fFunctionOk = TRUE;
}
__finally {
// Clean up all the resources.
if (lpBuf != NULL)
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
// Continue processing.
return (fFunctionOk);
}
例9 使用了中断处理句柄和关键词__leave的Funcarama4函数代码
try程序段内的关键词__leave导致程序运行指针直接跳到try程序段的结尾(你可以将此看成为跳到try程序段的结束花括弧)。这样,因为控制流程将“自然”的离开try程序段,进入finally程序段,所以不需付出额外代价而导致效率降低。但是你需要引进一个新的变量来指示整个函数的运行是否成功。
从try程序段到finally程序段,控制流程既可以是自然进入,也可以是由于异常的出现而导致控制流程过早离开try程序段而进入finally程序段。为确定何种情况下造成finally程序段的运行,我们可以调用AbnormalTermination函数来诊断。
BOOL AbnormalTermination(VOID);
该函数只能在finally程序段内调用以诊断与此finally相对应的try程序段是否是过早离开。如果AbnormalTermination的返回值是FALSE,表明程序流程是自然离开try程序段。否则,则是过早离