最近碰到了try 和 __try的區別的問題,經過實測與驗證,發現在vs2019下,確實存在try無法捕獲特定異常的問題,比如下面的代碼:
//以空格作為分割符的符號個數
//內存復制功能
// test1.cpp : 定義控制臺應用程序的入口點。
//
#include <Windows.h>
#include <tchar.h>
#include <winternl.h>
#include <Shlwapi.h>
#include <iostream>int Sub1(const char* v1);
CHAR* Sub2(const CHAR* Source, size_t size);const char* x = "11 11 1 ssssssssssss";int MemStandardTry()
{//仍然使用C++標準的try{}catch(…){}, 但在編譯命令行中加入 /EHa 的參數。這樣VC編譯器不會把try catch模塊給優化掉了。//注意 / EHa的大小寫try{BYTE* pch;pch = (BYTE*)00001234; //給予一個非法地址 *pch = 6; //對非法地址賦值,會造成Access Violation 異常 }catch (...){std::cout << "catched MemStandardTry" << std::endl;}return 0;
}int MemWinTry()
{__try{BYTE* pch;pch = (BYTE*)00001234; //給予一個非法地址 *pch = 6; //對非法地址賦值,會造成Access Violation 異常 }__except (EXCEPTION_EXECUTE_HANDLER){std::cout << "catched" << std::endl;}return 0;
}int main()
{MemStandardTry();MemWinTry();
// printf("%d\r\n", Sub1(x));
// printf("%d\r\n", Sub1(NULL));
// char* szChar = (char*)"11 11 1 ssssssssssss";
// printf("%s\r\n", Sub2(szChar, 50));return 0;}int Sub1(const char* v1)
{int length = -1;char* Buffer = NULL;__try{Buffer = (char*)malloc(strlen(v1) + 1);strcpy(Buffer, v1);char* pszToken = strtok(Buffer, "s");//在第一次調用 strtok 時,函數跳過前導分隔符(連在一起算一個)并返回指向在 strToken的第一個標記的指針,以空字符終止標記。//通過一系列 strtok 的調用,多個標記將被從 strToken 的其余部分拆開。 每個 strtok調用通過插入 null 字符在該調用返回 token 之后修改strToken。for (; pszToken != NULL; pszToken = strtok(NULL, "s"))length++;length++;}__except (EXCEPTION_EXECUTE_HANDLER){}free(Buffer);return(length);
}CHAR* Sub2(const CHAR* Source, size_t size)
{CHAR* v1 = NULL;__try{v1 = (CHAR*)malloc(size);memcpy(v1, Source, size);}__except (EXCEPTION_EXECUTE_HANDLER){free(v1);v1 = NULL;}return(v1);
}
在不做任何設置的情況下 MemStandardTry()在debug模式下可以捕獲異常 但是release無法捕獲,而MemWinTry()可以正常捕獲異常。
但是實際情況是,當我們按照注釋,設置 ,則發現try也可以在release模式下捕獲該異常。
//仍然使用C++標準的try{}catch(…){}, 但在編譯命令行中加入 /EHa 的參數。這樣VC編譯器不會把try catch模塊給優化掉了。
//注意 / EHa的大小寫
具體設置位置如下:
經過設置后,可以測試正確捕獲異常。
進一步的內容,可以參考C++ 異常捕獲 try 和 __try的區別_異常捕獲的方法與其區別-CSDN博客,謹此紀念。