Strict Standards: Non-static method Soojung::addReferer() should not be called statically in /home/lifthrasiir/sites/sapzil.info/soojung/settings.php on line 79

Warning: Cannot modify header information - headers already sent by (output started at /home/lifthrasiir/sites/sapzil.info/soojung/settings.php:79) in /home/lifthrasiir/sites/sapzil.info/soojung/classes/Counter.class.php on line 63

Strict Standards: Non-static method Entry::getEntry() should not be called statically in /home/lifthrasiir/sites/sapzil.info/soojung/entry.php on line 51

Strict Standards: Non-static method Soojung::entryIdToFilename() should not be called statically in /home/lifthrasiir/sites/sapzil.info/soojung/classes/Entry.class.php on line 182

Strict Standards: Non-static method Soojung::queryFilenameMatch() should not be called statically in /home/lifthrasiir/sites/sapzil.info/soojung/classes/Soojung.class.php on line 55
TokigunStudio3 | 블로그: 오늘의 삽질

내용으로 바로 넘어 가기


TokigunStudio3

228 / 3282   


더 이상 이 블로그는 운영되지 않습니다. 새 블로그로 가 주세요.

오늘의 삽질

2005/07/05 PM 10:17 | 개발/obfuscation | 12 comments | 0 trackbacks | AllBlog: vote, to pocket

거의 다섯 달을 끌어 오면서 막바지 작업을 하고 있는 Angolmois 개발 도중에 발생한 사건.

모든 작업이 끝나고 긴 identifier들을 모두 짧은 것으로 고치면서 그동안 남겨 놓았던 코드들을 정리하는 중이었다. 간단한 예를 보자면...
for(i=0; i<4; i++)
    if(!metadata[i]) {
        metadata[i] = malloc(1);
        metadata[i][0] = 0;
    }
이런 걸,
for(i=0; i<4; i++) if(!bm[i]) *(bm[i]=malloc(1))=0;
이렇게 고치는 과정인 것이다. (내가 짠 코드가 원래 개판이라는 건 좀 접어 두기로 하자 -_-;;;;)

이 과정을 다 해 놓고 나서 실행해 보니까 딴 건 다 잘 되는데 막판에 갑자기 segfault가 나는 것이었다. 혹시나 싶어서 printf를 중간에 넣어 보니까 segfault가 안 뜨는데 이 쯤에서 프로그램 중간에서 스택이 꼬여 버렸다는 걸 눈치챌 수 있었다. (옛날에 이것 때문에 한참 삽질한 적이 있어서 뼈저리게 느끼고 있다.) 이런 종류의 버그는 찾기가 엄청나게 힘들기 때문에 나는 한참 삽질하다가 segfault 안 나는 버전부터 다시 재작업을 하기로 했다.

...어느 순간에 갑자기 또 segfault가 난다. -_-;;;;;;;;;;;

이런 식으로 이틀동안 한 두어번 작업을 되풀이하다가 bms 파일을 파싱하는 부분에서 문제가 생겼다는 걸 알 수 있었다. 즉, 해당 부분의 원래 코드를 내가 작업한 코드로 고치면 에러가 나고 원래대로 돌리면 안 난다. 왜 그런가 살펴 봤더니...




문제가 발생한 부분은 이런 형식의 switch 구문이었다. (default:가 없다는 데 유의)
switch(i) {
case 1: do_something(); break;
case 2: do_another_thing(); break;
case 3: do_nothing(); break;
}
나는 이 코드를 처음에 다음과 같이 고쳤다. (여기서는 별 문제가 발생하지 않았다)
if(i==1) do_something();
else if(i==2) do_another_thing();
else if(i==3) do_nothing();
문제는 나중에 정리를 하면서 다음과 같이 고쳤던 것이다!
if(i==1) do_something();
if(i==2) do_another_thing();
if(i==3) do_nothing();
그리고 각각의 블록 안에서는 i를 고치는 부분이 있었기 때문에 엉뚱한 블록에 갑자기 잡히거나 하는 현상이 발생하면서 오류가 발생했던 것이었다. OTL

교훈: 앞으로는 obfuscation 할 때 로컬 RCS를 애용해야 겠다. 흑흑흑 ||orz

TrackBack URL: http://sapzil.info/soojung/trackback.php?blogid=629

Comment: mithrandir (1954/04/25 AM 11:20)

malloc(1)은 대체 뭐에욧

Comment: 에이쥬어 (2005/07/05 PM 11:37)

mithrandir // 1바이트짜리 동적 메모리 할당이요 -3-

Comment: 토끼군 (2005/07/05 PM 11:47)

에이쥬어: 정답 -3-

Comment: nohmad (2005/07/06 AM 03:01)

최근에 바이너리 서치란 표현을 배웠습니다. 오류가 없는 마지막 부분과 최근의 버전들을 이진 검색으로 비교해가면서 버그를 찾아내는 방법...

로컬 전용이라도 RCS 보다는 Subversion을 쓰는 것이 좋을 것 같네요.

Comment: mithrandir (2005/07/06 AM 09:37)

메모리 아깝잖아요오오오오오

Comment: Puzzlet Chung (2005/07/06 AM 11:04)

#define el else
#define ei else if

Comment: 디토 (2005/07/06 PM 12:44)

저..저건!!

Comment: 토끼군 (2005/07/06 PM 01:10)

nohmad: 문제는 제가 유지하고 있던 revision이 작업 중인 것과 마지막으로 정상으로 확인되었던 revision 두 개 뿐이었다는 것이었죠. 그래서 제가 미처 못 보고 넘어 갔던 버그가 두 revision에 함께 존재했던 거고요. RCS든 Subversion이든 아무튼 버전 관리 시스템은 절실히 필요하네요. orz
mithrandir: metadata가 필요할 때마다 null check 하는 것보단 낫죠 -3-
Puzzlet Chung: preprocessor directive는 모양 만들 때 초난감
디토: 새는 왱알앵알...

Comment: 이지 (2005/07/06 PM 03:22)

코딩 관련한 글에도 이렇게 코멘트가 많이 달리는군요!
다른 블로그들은 이런 글에 코멘트가 없던데! ㅋㅋ

Comment: 토끼군 (2005/07/06 PM 04:14)

이지: 어흐흐흑 orz

Comment: daybreker (2005/07/06 PM 04:19)

토끼군: 다 그런 거지.

Comment: 토끼군 (2005/07/08 PM 11:44)

daybreker: 날뷁에서 "날벩"으로 바뀌었군.

Copyright (c) 1995-2005, Kang Seonghoon (Tokigun).