2014-03-19 44 views
0

我似乎无法产生来自有意添加的算术错误一个核心转储文件在我的代码,那就是:feenableexcept没有产生核心转储

float x; 

x = 0.0/0.0; 

看来,当我创建了一个小实验程序协同工作来测试浮点异常,但是当我在实际应用程序中实现它时,它无法产生核心转储。

基本上,我试图产生一个可调试版本的版本,我在另一个文件(debuggable.c)中链接了一个函数,该函数使用GCC的构造函数属性来调用feenableexcept,该函数在主要初始化之前启用fpe异常。

debuggable.c:

void main_init(void) __attribute__((constructor)); 

void main_init(void) 
{ 
    printf("Enabling arithmetic exceptions\n"); 
    feenableexcept(fegetexcept()|FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 
}; 

然后在实际应用中的代码,我在故意算术错误添加到强制核心转储,但它似乎并没有工作。我已经验证feenableexcept确实被调用,并且它返回0以表示成功基于我添加的printf语句。此外,如果使用abort()函数,则会生成核心转储。

看来我已经正确地配置了Linux来生成核心转储文件,但是有一些关于应用程序编写或运行的方式并没有产生核心转储。

我想知道如果我可能会得到什么检查解决这个问题的建议。

这是Red Hat Linux版本我使用:

Red Hat Enterprise Linux Client release 5.4 (Tikanga) 
5.4 RedHawk Linux (Lima) 

这里是我的GCC版本:

gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46) 
Copyright (C) 2006 Free Software Foundation, Inc. 

是的,我知道它老了,但我有一个遗留系统工作。

更新1

看来,当我把故意算术错误在真正的应用程序的功能main(),它实际上炸弹和生产的核心转储。它不会在main()函数的被调用函数中执行此操作,除非您将调用feenableexcept()置于被调用函数本身中。

当我在一个简单的应用程序中测试它时,构造函数属性技术似乎可以在被调用函数中无需调用feenableexcept()。我想知道什么可能导致它在真正的应用程序中执行此操作?

更新2

我在几个地方叫我在实际应用中fegetexcept(),发现它调用setjmp()后立即返回0。看来setjmp()是C标准库的一部分,并且与longjmp()一起用于执行“非本地跳转”。

我不确定为什么它将异常标志重置为零。我最初以为我应该使用sigsetjmp()/siglongjmp()来保存信号,并已经调整了应用程序,但它也没有帮助。此外,我在我的小概念验证应用程序中测试了这一点,并且在调用setjmp()/sigsetjmp()之后,它不会将异常标志重置为零。我很难为什么setjmp()这样做。

回答

0

我似乎无法找到所需的信息表明为什么异常标志正在重置调用setjmp()longjmp()时为零。这在我的小概念验证程序中没有这样做。

我想到的一个工作是使用feholdexcept()setjmp()调用之前存储标志,然后再调用fesetenv()恢复标志。这允许程序抛出异常并像平常一样产生核心转储。我仍然好奇为什么setjmp()/longjmp()正在重置异常标志。如果有人知道,请发布答案。

1

我没有测试它,但我会认为这很可能不起作用,因为gcc认识到你的计算在编译时是一个常量表达式,只是将NaN赋值给x,不会触发异常。

在其他(IEEE)的话:中恒是安静的NaN,而不是一个信号的NaN

+0

如果这是解释,那么最简洁的解决方案(如果受GCC支持)是C99的'#pragma STDC FENV_ACCESS on'。这应该防止编译时计算'0.0/0.0'。一般来说,任何可能无法使用默认FPU标志执行的代码都应该使用该编译指示进行编译。 –

+0

@Pascal Cuoq:'#pragma STDC FENV_ACCESS on'功能似乎不被我的GCC版本所支持,因为它会一直指示它被忽略。我也尝试过这个[线程](http://stackoverflow.com/questions/6336786/floating-point-exceptions-gcc-bug)提供的GCC的'-frounding-math',这也没有帮助。 –

+0

来检查上述假设是否正确,如果可以使用非常量表达式(例如, x =(double)rand()/ 0.0; – mfro