2014-03-19 4 views
0

덤프, 즉 :feenableexcept 생산하지 코어 내 코드에서 의도적으로 추가 연산 오류에서 코어 덤프 파일을 생성 할 수없는 것

float x; 

x = 0.0/0.0; 
내가 작은 실험 프로그램을 만들 때 작동하는 것 같다

부동 소수점 예외를 테스트하지만 실제 응용 프로그램에서 구현 한 경우 코어 덤프가 생성되지 않습니다.

기본적으로 GCC의 생성자 속성을 사용하여 pre-main initialization에서 fpe 예외를 허용하는 feenableexcept을 호출하는 함수가 포함 된 다른 파일 (debuggable.c)에 링크 된 디버그 가능 릴리스 버전을 생성하려고합니다.

는 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이 실제로 호출되고 있고 printf 문을 기반으로 성공을 나타내는 0을 반환한다는 것을 확인했습니다. abort() 함수를 사용하면 코어 덤프가 생성됩니다.

코어 덤프 파일을 생성하기 위해 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() 함수에서 의도적 인 연산 오류를 배치, 그것을 실제로 폭탄을 보인다 코어 덤프를 생성합니다. 피 호출자 함수에 feenableexcept()을 호출하지 않는 한 main() 함수의 호출 수신자 함수에서이 작업을 수행하지 않습니다.

간단한 응용 프로그램에서 테스트했을 때 호출자 함수에서 feenableexcept()을 호출 할 필요없이 생성자 특성 기술이 작동하는 것 같습니다. 실제 응용 프로그램에서이 작업을 수행 할 수있는 원인이 무엇인지 궁금합니다.

업데이트 2

나는 여러 장소에서 내 실제 응용 프로그램에서 fegetexcept()에게 전화를 즉시 setjmp()에 대한 호출 후 0을 반환 발견했다. setjmp()은 C 표준 라이브러리의 일부이며 "non-local jumps"를 수행하기 위해 longjmp()과 함께 사용됩니다.

예외 플래그를 0으로 재설정하는 이유는 확실하지 않습니다.처음에는 신호를 보존하기 위해 sigsetjmp()/siglongjmp()을 사용해야한다고 생각하고 응용 프로그램을 적용하여 조정했지만 도움이되지 않았습니다. 또한, 작은 증거 개념의 응용 프로그램에서 이것을 테스트했지만 setjmp()/sigsetjmp() 호출 후 예외 플래그를 0으로 재설정하지 않았습니다. 나는 왜 setjmp()이 이런 일을하는지 잘 모르겠다.

답변

0

나는 이유를 예외 플래그가되고있다 리셋을 나타내는 정보를 찾을 수 없습니다 setjmp()longjmp()이 호출되면 0입니다. 그것은 내 작은 개념 증명 프로그램에서 이것을하지 않습니다.

제가 생각해 낸 문제는 을 사용하여 setjmp() 호출 전에 플래그를 저장 한 다음 나중에 fesetenv()을 호출하여 플래그를 복원하는 것입니다. 이로써 프로그램은 예외를 던져 정상적으로 코어 덤프를 생성 할 수있었습니다. 여전히 setjmp()/longjmp()이 예외 플래그를 재설정하는 이유에 대해 궁금합니다. 누구든지 대답을 게시하시기 바랍니다.

1

필자는 테스트하지 않았지만 gcc가 계산이 컴파일 타임에 상수 표현임을 알게되고 예외를 트리거하지 않을 x에 NaN을 할당하기 때문에 가장 가능성이 낮다고 가정합니다. 기타 (IEEE) 즉

는 : NaN이 시그널링 반대로 상수는 조용한 NaN이입니다

+0

이것이 설명 인 경우, GCC가 지원하는 경우 가장 깨끗한 해결책은 C99의'#pragma STDC FENV_ACCESS on'입니다. 이렇게하면 '0.0/0.0'의 컴파일 타임 계산을 막을 수 있습니다. 일반적으로 말해서, 기본 FPU 플래그로 실행되지 않는 코드는이 pragma로 컴파일해야합니다. –

+0

@Pascal Cuoq :'#pragma STDC FENV_ACCESS on' 기능은 GCC 버전에서 지원하지 않는 것 같습니다. 나는 또한이 [thread] (http://stackoverflow.com/questions/6336786/floating-point-exceptions-gcc-bug)에서 제안한 것처럼 GCC에서'-frounding-math'를 시도했지만 도움이되지 않았습니다. –

+0

위의 가정이 올바른지 확인하려면 상수 표현식이 아닌 다른 것으로 예외를 트리거 할 수 있습니다. x = (double) rand()/0.0; – mfro