C++ 异常捕获 try 和 __try的区别笔记

发布于:2025-05-11 ⋅ 阅读:(18) ⋅ 点赞:(0)

最近碰到了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博客,谨此纪念。