0

I can't seem to produce a core dump file from an intentionally added arithmetic error in my code, that is:

float x;

x = 0.0/0.0;

It seems to work when I created a small experimental program to test the floating point exception, but when I implemented it in the real application, it fails to produce the core dump.

Basicly, I am trying to produce a debuggable release version where I link in another file (debuggable.c) containing a function that uses GCC's constructor attribute to call feenableexcept which enables the fpe exceptions at pre-main initialisation.

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);
};

Then in the real application code, I added in the intentional arithmetic error to force a core dump but it does not seem to work. I have verified that feenableexcept is indeed being called and that it returns 0 to indicate success based on printf statements I added in. Furthermore, a core dump is produced if I use the abort() function.

It seems that I have configured Linux correctly to produce core dump files, but there is something about the way the application is written or ran that is not producing the core dumps.

I was wondering if I may get suggestions at what to check to fix this problem.

This is the version of Red Hat Linux I am using:

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

Here is my GCC version:

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

Yes, I know its old but I am working with a legacy system.

Update 1

It seems that when I place the intentional arithmetic error in the main() function of the real app, it actually bombs and produces the core dump. It is not doing this in a callee function of the main() function unless you put the call to feenableexcept() in the callee function itself.

The constructor attribute technique seems to work without the need to make a call to feenableexcept() in the callee function when I tested it out in a simple application. I'm wondering what could cause it to do this in the real application?

Update 2

I called fegetexcept() in my real application at several places and found out it returns 0 immediately after the call to setjmp(). It seems that setjmp() is part of the C standard library and is used with longjmp() to perform "non-local jumps".

I'm not sure why it is resetting the exception flags to zero though. I initially thought that I should be using sigsetjmp()/siglongjmp() to preserve the signals and have adapted the application to do so but it did not helped either. Furthermore, I tested this out in my little proof-of-concept app and it did not reset the exception flags to zero after the call to setjmp()/sigsetjmp(). I'm stumped at why setjmp() is doing this.

methon.dagger
  • 505
  • 9
  • 28

2 Answers2

1

I did not test it, but I would assume this most likely doesn't work since gcc realizes your calculation is a constant expression at compile time and just assigns NaN to x which won't trigger an exception.

In other (IEEE) words: the constant is a quiet NaN as opposed to a signaling NaN

mfro
  • 3,286
  • 1
  • 19
  • 28
  • If this is the explanation, then the cleanest solution, if supported by GCC, is C99's `#pragma STDC FENV_ACCESS on`. This should prevent the compile-time computation of `0.0 / 0.0`. Generally speaking, any code that may not be executed with the default FPU flags should be compiled with this pragma. – Pascal Cuoq Mar 19 '14 at 14:02
  • @Pascal Cuoq: The `#pragma STDC FENV_ACCESS on` feature does not seem to be supported by my GCC version as it keeps indicating that it is being ignored. I also tried the `-frounding-math` with GCC as suggested by this [thread](http://stackoverflow.com/questions/6336786/floating-point-exceptions-gcc-bug) here and that did not help either. – methon.dagger Mar 20 '14 at 03:51
  • to check if the above assumption is correct, you could try if you can trigger the exception with something that is not a constant expression, e.g. x = (double) rand()/0.0; – mfro Mar 20 '14 at 05:26
  • @mfro: I don't feel that is the case, because I tested the `x = 0.0/0.0` idea in my little program and it did throw the exception and produced a core dump. – methon.dagger Mar 20 '14 at 06:27
  • in your tests, did you use the same optimization level than have for your real application? – mfro Mar 20 '14 at 06:29
  • I changed the optimization flag to 0 ie `-O0` for the debug version. The release version had it set to 2 ie `-O2`. – methon.dagger Mar 20 '14 at 06:47
0

I can't seem to find the information to indicate why the exception flags are being reset to zero when setjmp() and longjmp() are called. It does not do this in my little proof-of-concept program.

A work around that I came up with was to use feholdexcept() to store the flags before the setjmp() call, and then call fesetenv() afterwards to restore the flags. This allowed the program to throw the exception and produce the core dumps as normal. I'm still curious as to why setjmp()/longjmp() is resetting the exception flags. If anyone knows please post the answer.

methon.dagger
  • 505
  • 9
  • 28