【try……catch】C++ try…… catch 笔记(C语言中也可以Try-Catch异常处理)

目录

 

C++ try……catch

catch(CException *e) 打印异常信息

 不经意间的内存泄露:try-catch(CException *e) [异常对象需要手动释放]

C++ try catch 捕获空指针异常,数组越界异常 

C++ try catch 异常类

异常类大全

C try……catch


没用用到MFC,是不支持CException的。

C++ try……catch

 

  • catch(CException *e) 打印异常信息

在进行各种各样的操作的时候,有时会出现未知的错误,又不知道什么类型的,一时摸不着头脑了,以前写过捕获的代码,但是用到的时候忘记了,现在记下来:

  try
 {
  MoveFile("D:\\fd.txt", "C:\\dbdw\\b.txt"); //将D:\fd.txt移动到C:\dbdw并改名为b.txt(原来目录下文件不存在)
 }
 catch(CException *e)//&e
 {
  TCHAR   szError[1024];   
  e->GetErrorMessage(szError,1024);   //  e.GetErrorMessage(szError,1024); 
  ::AfxMessageBox(szError); 
 }

那么这样就可以知道什么错误了!

 

  •  不经意间的内存泄露:try-catch(CException *e) [异常对象需要手动释放]

原本以为异常对象是不用手动释放的(即不用delete)

但今天发现跑了N天的服务器程序内存使用增大

在调试的时候也发现VS给出内存泄露的提示

才知道CException自带Delete方法且需要手动调用

像这样才对

try
{
	
}
catch (CException *e)
{
	e->Delete();
}

在尽量保证代码健壮性的前提下

再包上一层try-catch确实能够应对一些意外情况

但所有基于CException的异常不能直接delete

像下面的写法是错误的
try
{
	
}
catch (CException *e)
{
	delete e;
}

原文:https://blog.csdn.net/sidyhe/article/details/47400787

 

  • C++ try catch 捕获空指针异常,数组越界异常 (windows的 SEH)

 

 SEH的全称是Structured Exception Handling,是Windows操作系统提供的一种异常处理方式。SEH是属于操作系统的特性,不为特定语言设计,从它的名字就能看出它是一种结构化的异常处理方式。SEH包括了2个部分:终止处理__try/__finally和异常处理__try/__except,下面分别进行介绍。
   终止处理__try/__finally
        __try/__finally可以保证无论try块内的代码执行结果如何,finally块内的代码总会被调用和执行。现在用下面的这个VC++中的控制台程序来说明。


int _tmain(int argc, _TCHAR* argv[])

{

	__try

	{

		MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);

 

		// 除零,人为的使程序崩溃

		//

		int i = 13;

		int j = 0;

		int m = i / j;

	}

	__finally

	{

		// 在这里添加处理程序崩溃情况的代码

		//

 

		// 这里以弹出一个对话框为例子

		//

		MessageBox(NULL, _T("Message from '__finally' section"), _T("Test"), MB_OK);

	}

 

	MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);

 

	return 0;

}

   异常处理__try/__except
        __try/__except是用来捕捉异常的,只有当try块中的代码出现异常的时候,except块中的代码才会被调用和执行。它的语法是这样的:


__try

{

	// guarded code

}

__except(expression)

{

	 // exception handler code

}

它最大的一个好处就是可以完全控制异常进程。expression的值决定了异常被处理完后,进程该如何执行。下面依然用VC++中的控制台程序来说明。


int _tmain(int argc, _TCHAR* argv[])

{

	__try

	{

		MessageBox(NULL, _T("Message from '__try' section"), _T("Test"), MB_OK);

 

		// 除零,人为的使程序崩溃

		//

		int i = 13;

		int j = 0;

		int m = i / j;

	}

	__except(EXCEPTION_EXECUTE_HANDLER)

	{

		// 在这里添加处理程序崩溃情况的代码

		//

 

		// 这里以弹出一个对话框为例子

		//

		MessageBox(NULL, _T("Message from '__except' section"), _T("Test"), MB_OK);

	}

 

	MessageBox(NULL, _T("Funcation completed"), _T("Test"), MB_OK);

 

	return 0;

}

更多见:《让程序在崩溃时体面的退出之SEH》https://blog.csdn.net/starlee/article/details/6636723

 

以下是原文来旧文,但是尝试了不行,应该是博主写错了,应该是SEH

void TestEmptyPointType()  
{  
    try  
    {  
        int* p = NULL;  
        *p = 3;  
    }  
    catch(...)  
    {  
        cout<< "非法地址操作异常" << endl;  
    }  
}  
  
void TestDivZeroType()  
{  
    try  
    {  
        int b = 0;  
        int a = 3/b;  
    }  
    catch(...)  
    {  
        cout<< "0除异常" << endl;  
    }  
}  
  
void TestMemoryOutType()  
{  
    int * a = new int[4];  
    try  
    {  
        for (int i = 0; i<245; i++)  
        {  
            a++;  
        }  
        *a = 3;  
    }  
    catch(...)  
    {  
        cout<< "内存越界异常" << endl;  
    }  
}
  • C++ try catch 异常类

catch (CException *e) 的CException 就是一个类

主要

包括int、double(分别的)、exception(所有的)n等等类型。下面来超一段图表

异常类继承层级结构图如下:

每个类所在的头文件在图下方标识出来.

标准异常类的成员:

       ① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。

       ② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述;

       ③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。

    标准异常类的具体描述:



原文:https://blog.csdn.net/songzi1111/article/details/9299587

 

  • 异常类大全

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <memory>
#include <cstdlib>


int main(int argc, char *argv[])
{

    try
    {
        throw std::range_error("Hello Wolrd");

    } catch (std::range_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::underflow_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::overflow_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::length_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::out_of_range e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::invalid_argument e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::domain_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::runtime_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::logic_error e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::bad_cast e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::bad_alloc e)
    {
        std::cout << e.what() << std::endl;
        abort();
    } catch (std::exception e)
    {
        std::cout << e.what() << std::endl;
        abort();
    }catch(...)
    {
        std::cout<<"This fuck"<<std::endl;
    }

    return 0;
}

C try……catch

下午读了一篇名为《详解C的异常处理机制》的博文,才知道在C语言中,除了使用goto进行异常处理外,还可以使用setjmp和longjmp配合实现异常处理,而且比goto更加方便。如果利用C语言做一些宏定义,可以实现类似C++、Java等语言的try-catch结构。

博文《详解C的异常处理机制》链接地址


以下是根据该文介绍,写的关于try-catch的一些宏定义:

#ifndef __EXCEPION_H__
#define __EXCEPION_H__

#include

/// 异常标记
typedef struct tagExcepSign
{
    jmp_buf _StackInfo; // 保存异常处理入口的堆栈信息
    int _ExcepType; // 异常类型,0表示无异常,异常类型号一般取小于0的数
} ExcepSign;

/// 获取异常类型号
#define ExcepType(ExcepSign) ((ExcepSign)._ExcepType)

/// 可能抛出异常的代码块
#define Try(ExcepSign) if ( ((ExcepSign)._ExcepType = setjmp((ExcepSign)._StackInfo)) == 0 )

/// 捕获特定异常
#define Catch(ExcepSign, ExcepType) else if ((ExcepSign)._ExcepType == (ExcepType))

/// 捕获所有可能异常
#define CatchElse(ExcepSign) else if((ExcepSign)._ExcepType < 0)

/// 抛出异常
#define Throw(ExcepSign, ExcepType) longjmp((ExcepSign)._StackInfo, ExcepType)

#endif /* __EXCEPION_H__ */


下面的C代码使用了上述宏定义实现异常处理:

#include
#include "exception.h"

void ExceptionTest(int ExpType)
{
    ExcepSign Ex;

    // 异常类型号用负值表示
    ExpType = ExpType > 0 ? -ExpType : ExpType;

    Try(Ex) {
        if (ExpType < 0) {
            Throw(Ex, ExpType);
        }
        else {
            printf("没有异常\n");
        }
    } Catch(Ex, -1) {
        printf("异常类型:-1\n");
    } Catch(Ex, -2) {
        printf("异常类型:-2\n");
    } CatchElse(Ex) {
        printf("异常类型:未知(%d)\n", ExcepType(Ex));
    }
}

void Test(void)
{
    ExceptionTest(0); // 无异常
    ExceptionTest(1); // 异常1
    ExceptionTest(2); // 异常2
    ExceptionTest(3); // 异常3
}
---------------------
原文:https://blog.csdn.net/yangping_zheng/article/details/20781071
 

 

Linux_C实现try catch异常捕获

 

前言:像如java这样的面相对象语言,异常处理机制让其代码更具健壮性,可以代码捕获到如算术异常,空指针异常等,俘获并能够在预知情况下进行相应处理。那么对于C而言,是否能实现其功能?简要分析:Linux有对线程或者进程退出时有一种信号量机制,而默认情况下,这种signal是系统自己处理的,而最统一的处理方式是exit,而至于什么原因退出这个完全取决于什么样的信号。至于linux下的这些signal多少,哪个对应什么情况自行查阅资料。Linux_c 的实现将通过宏来实现。直接粗暴上代码吧:
--------------------- 
原文:https://blog.csdn.net/jekenzhuang/article/details/79737147 

exception.h


#ifndef EXCEPTION_H_

#define EXCEPTION_H_

 

#include <setjmp.h>

#include <signal.h>

 

/* MANPROCSIGnals.  */

#define	MANPROCSIG_HUP		1	/* Hangup (POSIX).  */

#define	MANPROCSIG_INT		2	/* Interrupt (ANSI).  */

#define	MANPROCSIG_QUIT		3	/* Quit (POSIX).  */

#define	MANPROCSIG_ILL		4	/* Illegal instruction (ANSI).  */

#define	MANPROCSIG_TRAP		5	/* Trace trap (POSIX).  */

#define	MANPROCSIG_ABRT		6	/* Abort (ANSI).  */

#define	MANPROCSIG_IOT		6	/* IOT trap (4.2 BSD).  */

#define	MANPROCSIG_BUS		7	/* BUS error (4.2 BSD).  */

#define	MANPROCSIG_FPE		8	/* Floating-point exception (ANSI).  */

#define	MANPROCSIG_KILL		9	/* Kill, unblockable (POSIX).  */

#define	MANPROCSIG_USR1		10	/* User-defined MANPROCSIG_nal 1 (POSIX).  */

#define	MANPROCSIG_SEGV		11	/* Segmentation violation (ANSI).  */

#define	MANPROCSIG_USR2		12	/* User-defined MANPROCSIG_nal 2 (POSIX).  */

#define	MANPROCSIG_PIPE		13	/* Broken pipe (POSIX).  */

#define	MANPROCSIG_ALRM		14	/* Alarm clock (POSIX).  */

#define	MANPROCSIG_TERM		15	/* Termination (ANSI).  */

#define	MANPROCSIG_STKFLT	16	/* Stack fault.  */

#define	MANPROCSIG_CLD		MANPROCSIG_CHLD	/* Same as MANPROCSIG_CHLD (System V).  */

#define	MANPROCSIG_CHLD		17	/* Child status has changed (POSIX).  */

#define	MANPROCSIG_CONT		18	/* Continue (POSIX).  */

#define	MANPROCSIG_STOP		19	/* Stop, unblockable (POSIX).  */

#define	MANPROCSIG_TSTP		20	/* Keyboard stop (POSIX).  */

#define	MANPROCSIG_TTIN		21	/* Background read from tty (POSIX).  */

#define	MANPROCSIG_TTOU		22	/* Background write to tty (POSIX).  */

#define	MANPROCSIG_URG		23	/* Urgent condition on socket (4.2 BSD).  */

#define	MANPROCSIG_XCPU		24	/* CPU limit exceeded (4.2 BSD).  */

#define	MANPROCSIG_XFSZ		25	/* File size limit exceeded (4.2 BSD).  */

#define	MANPROCSIG_VTALRM	26	/* Virtual alarm clock (4.2 BSD).  */

#define	MANPROCSIG_PROF		27	/* Profiling alarm clock (4.2 BSD).  */

#define	MANPROCSIG_WINCH	28	/* Window size change (4.3 BSD, Sun).  */

#define	MANPROCSIG_POLL		MANPROCSIG_IO	/* Pollable event occurred (System V).  */

#define	MANPROCSIG_IO		29	/* I/O now possible (4.2 BSD).  */

#define	MANPROCSIG_PWR		30	/* Power failure restart (System V).  */

#define MANPROCSIG_SYS		31	/* Bad system call.  */

#define MANPROCSIG_UNUSED	31

 

#define T Exception_t

typedef struct Exception_t{

	char *reason;

}Exception_t;

 

typedef struct Exception_frame{

	struct Exception_frame *prev;

	jmp_buf env;

	const char *file;

	int line;

	const T* exception;

}Exception_frame;

 

extern Exception_frame *Exception_stack;

 

enum{

	EXCEPTION_ENTERED=0,

	EXCEPTION_RAISED,

	EXCEPTION_HANDLED,

	EXCEPTION_FINALIZED

};

/* Manage all process signal,and automanage signal by process cause exit directoryly,*/

#define ManProcAllSig \

		    int sum = 31; \

			while(sum){ \

				signal(sum,handle_proc_sig); \

				sum--; \

			}

/*Throw a exception*/

#define throw(e) exception_raise(&(e),__FILE__,__LINE__)

 

#define rethrow exception_raise(exception_frame.exception, \

		               exception_frame.file,exception_frame.line)

 

void handle_proc_sig(int signo);

 

void abort_without_exception(const Exception_t *e,const char *file,int line);

 

void exception_raise(const T *e,const char *file,int line);

 

#define try do{ \

				volatile int exception_flag; \

				Exception_frame exception_frame; \

				exception_frame.prev = Exception_stack; \

				Exception_stack = &exception_frame; \

				ManProcAllSig \

				exception_flag = setjmp(exception_frame.env); \

				if (exception_flag == EXCEPTION_ENTERED) \

				{

 

#define catch(e) \

		if(exception_flag == EXCEPTION_ENTERED) \

			Exception_stack = Exception_stack->prev; \

		}else if(exception_flag == e){ \

			exception_flag = EXCEPTION_HANDLED;

 

#define try_return \

			switch(Exception_stack = Exception_stack->prev,0) \

				default: return

 

#define catch_else \

			if(exception_flag == EXCEPTION_ENTERED) \

				Exception_stack = Exception_stack->prev; \

		    }else if(exception_flag != EXCEPTION_HANDLED){ \

		    	exception_flag = EXCEPTION_HANDLED;

 

#define end_try \

				if(exception_flag == EXCEPTION_ENTERED) \

					Exception_stack = Exception_stack->prev; \

		    	} \

		    	if (exception_flag == EXCEPTION_RAISED) \

		    		exception_raise(exception_frame.exception, \

		    				exception_frame.file,exception_frame.line); \

				}while(0)

 

#define finally \

				if(exception_flag == EXCEPTION_ENTERED) \

					Exception_stack = Exception_stack->prev; \

				}{ \

					if(exception_flag == EXCEPTION_ENTERED) \

							exception_flag = EXCEPTION_FINALIZED;

 

 

#undef T

#endif /* EXCEPTION_H_ */

exception.c


#include "exception.h"

#include <stdio.h>

#include <assert.h>

Exception_frame *Exception_stack = NULL;

 

void exception_raise(const Exception_t *e,const char *file,int line){

	Exception_frame *p = Exception_stack;

 

	assert(e);

	if(p == NULL){

		abort_without_exception(e,file,line);

	}

 

	p->exception = e;

	p->file = file;

	p->line = line;

	Exception_stack = Exception_stack->prev;

	longjmp(p->env,EXCEPTION_RAISED);

}

 

void abort_without_exception(const Exception_t *e,const char *file,int line){

	//fprintf(stderr,"Uncaught exception");

	if(e->reason)

		fprintf(stderr," %s",e->reason);

	else

		fprintf(stderr,"at 0x%p",e);

	if(file && line > 0)

		fprintf(stderr, "raised at %s:%d\n",file,line);

	fprintf(stderr,"aborting...\n");

	fflush(stderr);

	abort();

}

 

void handle_proc_sig(int signo){

 

	if( signo == MANPROCSIG_HUP )

	    printf(" Hangup (POSIX).  \r\n");

	else if( signo == MANPROCSIG_INT	)

		printf(" Interrupt (ANSI).  \r\n");

	else if( signo == MANPROCSIG_QUIT )

		printf(" Quit (POSIX).  \r\n");

	else if( signo == MANPROCSIG_ILL	)

		printf(" Illegal instruction (ANSI).  \r\n");

	else if( signo == MANPROCSIG_TRAP )

		printf(" Trace trap (POSIX).  \r\n");

	else if( signo == MANPROCSIG_ABRT )

		printf(" Abort (ANSI).  \r\n");

	else if( signo == MANPROCSIG_IOT )

		printf(" IOT trap (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_BUS )

		printf(" BUS error (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_FPE )

		printf(" Floating-point exception (ANSI).  \r\n");

	else if( signo == MANPROCSIG_KILL )

		printf(" Kill, unblockable (POSIX).  \r\n");

	else if( signo == MANPROCSIG_USR1 )

		printf(" User-defined signal if( signo == (POSIX).  \r\n");

	else if( signo == MANPROCSIG_SEGV )

		printf(" Segmentation violation (ANSI).  \r\n");

	else if( signo == MANPROCSIG_USR2 )

		printf(" User-defined signal 2 (POSIX).  \r\n");

	else if( signo == MANPROCSIG_PIPE )

		printf(" Broken pipe (POSIX).  \r\n");

	else if( signo == MANPROCSIG_ALRM )

		printf(" Alarm clock (POSIX).  \r\n");

	else if( signo == MANPROCSIG_TERM )

		printf(" Termination (ANSI).  \r\n");

	else if( signo == MANPROCSIG_STKFLT )

		printf(" Stack fault.  \r\n");

	else if( signo == MANPROCSIG_CLD )

		printf(" Same as SIGCHLD (System V).  \r\n");

	else if( signo == MANPROCSIG_CHLD )

		printf(" Child status has changed (POSIX).  \r\n");

	else if( signo == MANPROCSIG_CONT )

		printf(" Continue (POSIX).  \r\n");

	else if( signo == MANPROCSIG_STOP )

		printf(" Stop, unblockable (POSIX).  \r\n");

	else if( signo == MANPROCSIG_TSTP )

		printf(" Keyboard stop (POSIX).  \r\n");

	else if( signo == MANPROCSIG_TTIN )

		printf(" Background read from tty (POSIX).  \r\n");

	else if( signo == MANPROCSIG_TTOU )

		printf(" Background write to tty (POSIX).  \r\n");

	else if( signo == MANPROCSIG_URG	)

		printf(" Urgent condition on socket (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_XCPU )

		printf(" CPU limit exceeded (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_XFSZ )

		printf(" File size limit exceeded (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_VTALRM )

		printf(" Virtual alarm clock (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_PROF )

		printf(" Profiling alarm clock (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_WINCH )

		printf(" Window size change (4.3 BSD, Sun).  \r\n");

	else if( signo == MANPROCSIG_POLL )

		printf(" Pollable event occurred (System V).  \r\n");

	else if( signo == MANPROCSIG_IO )

		printf(" I/O now possible (4.2 BSD).  \r\n");

	else if( signo == MANPROCSIG_PWR )

		printf(" Power failure restart (System V).  \r\n");

	else if( signo == MANPROCSIG_SYS)

		printf(" Bad system call.  \r\n");

	else if( signo == MANPROCSIG_UNUSED)

		printf(" Unknow erroe.  \r\n");

 

	Exception_frame *p = Exception_stack;

	Exception_stack = Exception_stack->prev;

	longjmp(p->env,signo);

//	exit(0);//exit process

}

测试:test.c


#include <stdio.h>

#include <signal.h>

#include <stdlib.h>

#include "exception.h"

#include <unistd.h>

 

void test1(){

	char* a = NULL;

	*a = 1;

}

void test2(){

	int num = 1;

	while(1){

		printf("number=%d\r\n",num++);

		sleep(1);

	}

}

int main(){

 

	try{

 

      test2();//Simulate NULL pointer exception!!

	}catch(MANPROCSIG_SEGV){ //Catch the exception

		printf("NULL pointer !!\r\n");

	}catch_else{

		printf("Unknow Error!!\r\n");

	}finally{

		printf("DONE \r\n");

	}end_try;

	return 0;

 

}

 Linux 下 C++ 异常处理技巧

https://www.jianshu.com/p/4e14ba11fe78

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值