目录

 

​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》​​​

 

以下是原文来旧文,但是尝试了不行,应该是博主写错了,应该是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等等类型。下面来超一段图表

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

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

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

标准异常类的成员:

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

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

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

    标准异常类的具体描述:


 

  • 异常类大全
#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

}

 

 

Linux_C实现try catch异常捕获

 

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


#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;



}