此代码是否包含隐藏的错误
Does this code contain a hidden bug?
以下代码:
- 在gcc版本4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5/32bits)下运行良好
- 使用MSVC10 (win7/32位)编译时运行良好
- gcc 4.5.2 (MinGW on win7/32位)
main.cpp :
# include <iostream>
# include <csetjmp>
# include <stdexcept>
using namespace std ;
void do_work(jmp_buf context)
{
try
{
throw runtime_error("Ouch !") ;
}
catch(exception & e)
{
}
longjmp(context, -1) ; //BP1
}
int main(int, char *[])
{
jmp_buf context ;
try
{
if( setjmp(context) != 0 )
{
throw runtime_error("Oops !") ; //BP2
}
do_work(context) ;
}
catch(exception & e)
{
cout << "Caught an exception saying : " << e.what() << endl ;
}
}
我试着调试它,但程序行为奇怪。有时我可以越过第一个断点(BP1),然后在BP2处崩溃,有时控制永远不会到达BP1,就像程序陷入无限循环一样。以我的调试技能,我不能说更多了。
这段代码是我能得到的显示MinGW 4.5奇怪行为的最小代码。我还注意到:
- 如果我将
do_work
函数调用替换为它的内容,程序运行良好。 - 如果我在
do_work
中删除try{ ... } catch(...){ }
块,程序运行良好。 - 优化标志没有效果(总是崩溃)。
我知道c++代码中的setjmp/longjmp
问题,但我被迫使用它来与一些遗留的C代码接口。
我的问题:
- 这是一个错误的/错误的/错误的代码吗?还是mingw4.5错误地处理了代码?(这是苛刻和冒昧的指责工具,但我怀疑其中的一些设置)。
谢谢你的建议。
必要时请重新标记
Unix上的longjmp(3)手册页说:
longjmp()例程不能在调用setjmp()例程返回
我认为它解释了你所关心的"有时控制永远达不到BP1"。我不认为"运行良好"是可靠的判断。我更希望它随机运行良好,通常是搞乱堆栈。
在将longjmp/setjmp与c++异常混合使用时,为了避免崩溃和未定义的行为,有一些明确的建议应该考虑进去:
- 不要在c++程序中使用setjmp/longjmp。
- 如果你在可能发生异常的程序中使用setjmp/longjmp函数,只要它们不交互,你就是安全的。 永远不要跳出try和catch子句。
- 永远不要跳过自动对象初始化点。
- 永远不要长跳自动对象的破坏点,特别是如果析构函数是非平凡的。 永远不要从信号处理程序抛出。
- 永远不要从嵌套的信号处理程序调用longjmp。
- 从位置X到位置Y的长跳行为保持可预测和有效,只要在X抛出和在X捕获的异常具有相同的效果。
- 如果你混合使用setjmp/longjmp和异常,不要期望可移植性 相反,请参考您正在使用的文档编译器中的相关详细信息。例如,如果你使用Visual c++,读取use setjmp/longjmp
问题提到在用c++编写的程序中处理遗留的C代码。在审查一个Boost库时,对jpeg库中的sjlj问题进行了有趣的讨论。讨论很长,但这里是推荐选项的要点。
c++对longjmp()
的使用只有一个额外的限制:
如果将控制转移到程序中的另一个(目标)点的抛出异常会破坏任何自动对象,那么在将控制转移到相同(目标)点的抛出点上调用longjmp(jbuf, val)具有未定义的行为。 (18.7)
你似乎意识到了这一点,而你的程序没有做到这一点。
longjmp
和setjmp
是c函数,用c++异常处理语义和对象销毁语义调用它们是未定义的行为,这意味着它取决于实现是否有效(您的测试显示了这一点,SEH堆栈展开语义打破了东西,取决于使用的类型,如果您的工作使用的是dwarf2)
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- C++ [错误] 声明'char '隐藏参数。什么意思?
- 我正在调试这个C++程序.编译器不再显示语法错误,但存在隐藏的逻辑错误
- 关于隐藏,覆盖和虚拟表的汇编错误
- 问题5.1-QMessageBox错误?如果在QDialog隐藏时调用了QMessageBox,则程序退出(0)
- 隐藏的 G++ 引用错误
- 隐藏 sh: -c 在 c++ Linux 中调用“system”时的错误消息
- 如何在gcc错误消息中隐藏默认模板参数
- 此代码是否包含隐藏的错误