오늘 나를 5시간의 삽질러 몰고간 컴파일러 경고를 소개하고자 한다. 프로그램 최종 테스트 중 JNI와 연동된 모듈 중 하나가 돌연사하는 상황이 일어났다. 그것은 Segmentation fault (core dumped)
C언어를 해본 사람이라면 대략 어떤 경유로 프로그램이 죽었는지 알 수있다.
대부분 Segmentation fault (core dumped) 은 메모리 혹은 포인터의 사용과 관련된 경우가 많다. 오늘의 버그도 하나의 실수이겠거니 하고 개발환경에서 디버깅을 하는데 싸한 느낌이왔는데 바로 배포 환경에서만 프로그램이 죽는 것이다.
가장먼저 최근 변경된 코드를 뒤지기 시작했다. 변경 이력을 보여 관련된 로그를 추가하고 테스트를 여러번 돌리던 중 특정 함수 라인에서 프로그램이 돌연사하는 것을 알게되었다.
int main() {
TimeStamp *timestamp = (TimeStamp *) malloc(sizeof(timestamp));
struct tm *lt, tm_buf;
time_t tt;
int ret = 0;
tt = time(NULL);
lt = gmtime_r(&tt, &tm_buf);
if (lt == NULL)
ret = -1;
else {
// int a = b + 1900;
timestamp->year = lt->tm_year + 1900; // 사망하셨습니다.
return 0;
}
슬프게도 사망 라인은 개발 환경에서 디버깅이 더럽게 잘되는 상황을 맞이하게 된다. 심지서 사망라인을 풀어쓰자면 `int a = b + 1900; 그럼 코드가 잘못되었다는 것은 아닐테니 환경을 의심했다.
그렇다. 해당 프로젝트는 거지같은 보안 라이브러리 정책으로 인해 소스코드를 직접 업로드하여 컴파일->링킹->빌드 과정을 거쳐야만 했다. 조사 결과 다음의 차이가 있었다.
공교롭게도 이 두 번째 의심이 나를 5시간이라는 지옥 불구덩이 속으로 몰아넣었다. GCC
버전 OS
버전으 맞추기 위해 이것 저것 알아보고 찾아보는 헛 발질을 계속하게 되었다. 그러던 우연히 컴파일 도중 내 눈에 들어온 경고 알람이 있으니...
main.c:19:10: warning: implicit declaration of function ‘gmtime_r’; did you mean ‘gmtime’? [-Wimplicit-function-declaration]
GCC 컴파일러는 이미 나에게 충분한 경고를 때려 넣고 있었다. 해당 경고를 해석하자면....
"gmtime_r 혹시 gmtime 쓰려는거 아니니? 뭐 일단 비슷한거 같으니.. 프로그램은 실행 가능해~"
순간 당황했다. 해당 함수의 선언을 따라가다 보니 해답을 얻을 수 있었다.
/* Return the `struct tm' representation of *TIMER
in Universal Coordinated Time (aka Greenwich Mean Time). */
extern struct tm *gmtime (const time_t *__timer) __THROW;
#ifdef __USE_POSIX
/* Return the `struct tm' representation of *TIMER in UTC,
using *TP to store the result. */
extern struct tm *gmtime_r (const time_t *__restrict __timer,
struct tm *__restrict __tp) __THROW;
#endif /* POSIX */
내가 사용하는 gmtime_r 전처리 문에 의하여 감싸져 있다. 저것은 컴파일시 옵션(__USE_POSIX)에 따라 해당 코드를 추가 할 것인지, 안하고 빌드 할 것인지에 대한 것이다. 배포 환경을 확인 해보니 GCC 컴파일 옵션 (-std=c99)이 적용되어 있었다. 결론적으로 나는 없는 함수를 불러내어 실행하려 했던 것으로 그 결과 프로그램이 죽을 수 밖에 없는 것이었다.
이번 5시간의 여정은 컴파일 경고의 무시로 부터 시작되었다. 타입의 캐스팅이 조금만 달라고 컴파일을 안해주는 JAVA와 다르게 C언어는 없어도 해주는 경우가 있다. 그 경고가 implicit declaration 같은 경고이다. 마지막으로 옵션에 대한 정리를 하고 마무리 하고자 한다...
아 JAVA하고 싶다.