c语言linux异常处理,【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..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..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等等类型。下面来超一段图表

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

67cc8f859ac310bb6e0c2aaceb4d24ae.png

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

标准异常类的成员:

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

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

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

标准异常类的具体描述:

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

异常类大全

#include

#include

#include

#include

#include

#include

#include

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<

}

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..net/yangping_zheng/article/details/20781071

Linux_C实现try catch异常捕获

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

---------------------

原文:https://blog..net/jekenzhuang/article/details/79737147

exception.h

#ifndef EXCEPTION_H_

#define EXCEPTION_H_

#include

#include

/* MANPROCSIGnals. */

#defineMANPROCSIG_HUP1/* Hangup (POSIX). */

#defineMANPROCSIG_INT2/* Interrupt (ANSI). */

#defineMANPROCSIG_QUIT3/* Quit (POSIX). */

#defineMANPROCSIG_ILL4/* Illegal instruction (ANSI). */

#defineMANPROCSIG_TRAP5/* Trace trap (POSIX). */

#defineMANPROCSIG_ABRT6/* Abort (ANSI). */

#defineMANPROCSIG_IOT6/* IOT trap (4.2 BSD). */

#defineMANPROCSIG_BUS7/* BUS error (4.2 BSD). */

#defineMANPROCSIG_FPE8/* Floating-point exception (ANSI). */

#defineMANPROCSIG_KILL9/* Kill, unblockable (POSIX). */

#defineMANPROCSIG_USR110/* User-defined MANPROCSIG_nal 1 (POSIX). */

#defineMANPROCSIG_SEGV11/* Segmentation violation (ANSI). */

#defineMANPROCSIG_USR212/* User-defined MANPROCSIG_nal 2 (POSIX). */

#defineMANPROCSIG_PIPE13/* Broken pipe (POSIX). */

#defineMANPROCSIG_ALRM14/* Alarm clock (POSIX). */

#defineMANPROCSIG_TERM15/* Termination (ANSI). */

#defineMANPROCSIG_STKFLT16/* Stack fault. */

#defineMANPROCSIG_CLDMANPROCSIG_CHLD/* Same as MANPROCSIG_CHLD (System V). */

#defineMANPROCSIG_CHLD17/* Child status has changed (POSIX). */

#defineMANPROCSIG_CONT18/* Continue (POSIX). */

#defineMANPROCSIG_STOP19/* Stop, unblockable (POSIX). */

#defineMANPROCSIG_TSTP20/* Keyboard stop (POSIX). */

#defineMANPROCSIG_TTIN21/* Background read from tty (POSIX). */

#defineMANPROCSIG_TTOU22/* Background write to tty (POSIX). */

#defineMANPROCSIG_URG23/* Urgent condition on socket (4.2 BSD). */

#defineMANPROCSIG_XCPU24/* CPU limit exceeded (4.2 BSD). */

#defineMANPROCSIG_XFSZ25/* File size limit exceeded (4.2 BSD). */

#defineMANPROCSIG_VTALRM26/* Virtual alarm clock (4.2 BSD). */

#defineMANPROCSIG_PROF27/* Profiling alarm clock (4.2 BSD). */

#defineMANPROCSIG_WINCH28/* Window size change (4.3 BSD, Sun). */

#defineMANPROCSIG_POLLMANPROCSIG_IO/* Pollable event occurred (System V). */

#defineMANPROCSIG_IO29/* I/O now possible (4.2 BSD). */

#defineMANPROCSIG_PWR30/* Power failure restart (System V). */

#define MANPROCSIG_SYS31/* Bad system call. */

#define MANPROCSIG_UNUSED31

#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

#include

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

#include

#include

#include "exception.h"

#include

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值