目录
catch(CException *e) 打印异常信息
不经意间的内存泄露:try-catch(CException *e) [异常对象需要手动释放]
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等等类型。下面来超一段图表
异常类继承层级结构图如下:
每个类所在的头文件在图下方标识出来.
标准异常类的成员:
① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。
② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述;
③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。
标准异常类的具体描述:
- 异常类大全
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 的实现将通过宏来实现。直接粗暴上代码吧:
/* MANPROCSIGnals. */
/* Hangup (POSIX). */
/* Interrupt (ANSI). */
/* Quit (POSIX). */
/* Illegal instruction (ANSI). */
/* Trace trap (POSIX). */
/* Abort (ANSI). */
/* IOT trap (4.2 BSD). */
/* BUS error (4.2 BSD). */
/* Floating-point exception (ANSI). */
/* Kill, unblockable (POSIX). */
/* User-defined MANPROCSIG_nal 1 (POSIX). */
/* Segmentation violation (ANSI). */
/* User-defined MANPROCSIG_nal 2 (POSIX). */
/* Broken pipe (POSIX). */
/* Alarm clock (POSIX). */
/* Termination (ANSI). */
/* Stack fault. */
/* Same as MANPROCSIG_CHLD (System V). */
/* Child status has changed (POSIX). */
/* Continue (POSIX). */
/* Stop, unblockable (POSIX). */
/* Keyboard stop (POSIX). */
/* Background read from tty (POSIX). */
/* Background write to tty (POSIX). */
/* Urgent condition on socket (4.2 BSD). */
/* CPU limit exceeded (4.2 BSD). */
/* File size limit exceeded (4.2 BSD). */
/* Virtual alarm clock (4.2 BSD). */
/* Profiling alarm clock (4.2 BSD). */
/* Window size change (4.3 BSD, Sun). */
/* Pollable event occurred (System V). */
/* I/O now possible (4.2 BSD). */
/* Power failure restart (System V). */
/* Bad system call. */
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,*/
/*Throw a exception*/
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);
/* EXCEPTION_H_ */
exception.c
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
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;
}