paip.c++ gcc 不能捕获exception异常的解决
paip.c++ gcc 不能捕获exception异常的解决
作者Attilax , EMAIL:1466519819@qq.com
来源:attilax的专栏
地址:http://blog.csdn.net/attilax
现象:
////////////
不能捕获 "index out of range", 下标越界异常...经过测试,只能捕获手动throw出来的异常..使用windows的__try ____except,,QT 的QT_try QT_catch 都是不行..
原因"
////////////////
c++标准 try, catch, throw是C++标准里的语法,标准只要求try catch捕获throw出来的异常,并不要求捕获系统异常(如被0除,段错误,CPU异常等)。从C++层面来说,不要期望try, catch能捕获系统异常。
GCC所实现的C++异常处理框架中,它的catch(…)语法,并不能捕获系统异常。因此,这给C++中异常处理的良好运用打了大大的折扣;不同类型的系统异常等。所以Linux操作系统上的gcc编译的程序中,它只能捕获程序中,曾经被自己显式地throw出来的异常,而对于系统异常,catch block是毫无办法的。
解决:
///////////////
a.windows系统,调用.Using a Vectored Exception Handler..SEH机制来解决.比较麻烦.
b.linux系统,信号来调用...比较麻烦.
c.自己多加判断,正则表达式是个好东西..
异常的类型:
//////////////////
分为手动throw出来的异常..可以捕获..
系统异常(如被0除,段错误,CPU异常等)
别的资料.
//////////////
ry{} catch(…){}
以前都是用try{} catch(…){}来捕获C++中一些意想不到的异常, 今天看了Winhack的帖子才知道,这种方法在VC中其实是靠不住的。例如下面的代码:
try
{
BYTE* pch ;
pch = ( BYTE* )00001234 ; //给予一个非法地址
*pch = 6 ; //对非法地址赋值,会造成Access Violation 异常
}
catch(...)
{
AfxMessageBox( "catched" ) ;
}
这段代码在debug下没有问题,异常会被捕获,会弹出”catched”的消息框。 但在Release方式下如果选择了编译器代码优化选项,则VC编译器会去搜索try块中的代码, 如果没有找到throw代码, 他就会认为try catch结构是多余的, 给优化掉。 这样造成在Release模式下,上述代码中的异常不能被捕获,从而迫使程序弹出错误提示框退出。
那么能否在release代码优化状态下捕获这个异常呢, 答案是有的。 就是__try, __except结构, 上述代码如果改成如下代码异常即可捕获。
__try
当然有, 就是仍然使用C++标准的try{}catch(..){}, 但在编译命令行中加入 /EHa 的参数。这样VC编译器不会把try catch模块给优化掉了。
找到一篇比较好的英文文章谈这个问
那么C++标准中对于这种同一个程序有不同的运行结果有何解释呢?这里需要注意的是,window2000系统下catch(…)能捕获住系统异常, 这完全是它自己的扩展。在C++标准中并没有要求到这一点,它只规定catch(…)必须能捕获程序中所有通过throw语句抛出的异常。因此上面的这个 程序在linux系统下的运行结果也完全是符合C++标准的。虽然大家也必须承认window2000系统下对C++异常处理模型的这种扩展确实是一个很 不错的完善,极大得提高了程序的安全性。
以上代码Debug版本运行不会弹对话框,因为"除零异常"了。而Release版本会弹,是因为变量a没有用到,被编译器优化掉了。若要使其不优化掉,把a使用printf函数打印出来。
可以去掉汇编实现的try,catch,看看编译器会不会报错!
最近看书时,看到异常处理中有try……except……
通常try -except是用来处理SEH异常的,而不是标准异常。具体参考下面的资料。
这两个都讲的很详细~
c++ try-except statement
在Windows系统中,使用VC2005编译的debug版本代码,try, catch能捕获到被0除异常,在网上查找下,说的是VC编译器对try, catch作了扩展,使用了Windows特有的结构化异常处理(tructured Exception Handling,SEH)机制,据说要在release版本中使用SEH,要选择编译选项/Eha,这我没有试过。
摘抄一段话:SEH异常和C++异常有本质的区别, SEH是操作系统提供的异常处理技术, 在任何支持该操作系统的编程语言中, 都可以使用, 而C++异常处理只能在编写C++代码时使用。然而, 应当知道WINDOWS的VC++编译器是使用操作系统结构化异常来实现C++异常的. 也就是说, C++的try块在VC++下编译时, 会变成__try块, C++的catch块会变成SEH的 __except块: catch测试则变成SEH异常过滤器, catch中的代码则变为__except中的代码. 事实上, C++的throw块, 在编译的时候也会变成SEH的RaiseException函数调用, 由c++异常变为SEH异常.(http://blog.csdn.net/ydbcsdn/article/details/5271755)
在linux下,使用g++去编译时,try, catch是无法捕获被0除异常的,这我试过,不清楚是否有编译选项支持,即使不支持,也是合理的,因为C++标准并不要求支持。
若想代码易于移植,或适用于多种系统,不要期望try,catch去捕获系统异常,若明确知道只使用于windows系统除外,但要记得打开编译选项/Eha,否则达不到你的期望。
参考:
第21集 Windows系列操作系统平台中所提供的异常处理机制:希赛网软件工程频道.htm
(imp)C++-MinGW能支持VC的__try的语法吗? - 德问 编程社交问答.htm
SEH异常,每个程序员都应当引起重视。 - CSDN论坛 - CSDN.NET.htm
imp...Using a Vectored Exception Handler (Windows).htmimp.
try?catch误区_zhoujie_liang_新浪博客.htm
imp....C语言的异常机制 setjump longjump函数【转】 - 红联Linux门户 - 中国领先的Linux技术网站 - 网站导航 - Linux通用技术 - Linux编程与内核.htm
imp,imp...C++-MinGW能支持VC的__try的语法吗? - 德问 编程社交问答.htm
// QT_CATCH(...)
// catch(...)
// catch(...)