BLOG main image
분류 전체보기 (376)
Yuno (176)
Travel (99)
Culture (46)
Other (13)
Programming (13)
Picture (22)

«   2010/03   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
1,246,379 Visitors up to today!
Today 27 hit, Yesterday 272 hit
'Programming'에 해당되는 글 13건
[Yuno.org, 2009/07/04 02:24, Programming]


최근에 VS 2003으로 프로젝트 컴파일을 하면 이상하게 디버거가 죽어버리는 현상을 겪고 있다. 로컬라이제이션을 위해서 SVN에서 Branch를 따서 코드 관리를 하고 있는데 가끔 여러 코드를 동시에 컴파일해서 배포 해야 하는 경우가 생긴다.

그러던 어느날 부터 갑자기(!) 비주얼 스튜디오로 컴파일 하고, 링커가 결과 물을 뱉어 낸 후에 디버거가 달라 붙어서 실행 되는 순간! vs 2003이 뻗어버린다.

-_-

process를 봐도 보통 160mb 정도의 메모리와 함께 실행 되는 녀석이 300kb 정도만 로드 하고는 그대로- 침묵.

한참을 기다려도 소용이 없다. 수차례 시도 하면 결국은 한번쯤 무사히 실행이 되는데 이때 첫 실행때는 vs2003이 좀 바보가 된다. 이때 실행된 프로젝트 파일을 정상 종료하고 다시 실행하면 그 다음부터는 전-혀- 문제 없이 작동하는 이상한 현상이 계속 나타나고 있다. 젠장!

오늘도 10분이상 10번도 넘게 실행했다가 vs 죽이고, 실행 했다가 죽이고를 반복하고 겨우 실행.. 짜증 정말..

그래서 2003을 버리고 안정적일 것만 같은 2005로 가기로 결정! 추가 작업이 필요 할 것 같아서 소스 코드 사본을 하나 더 만들고 사본에서 2005으로 변환 작업 시작.

...

이게 정말 2003에서 컴파일 되던게 맞나 싶을 정도로 쏟아져 나오는 에러들..

무난했던 에러들은 const static var 선언 같은 이전 버전에서는 암묵적으로 int 형으로 받아주는 것들이 이제는 깐깐해져서 나오는 에러인 C4430 에러 백개 정도는 단순히 형 타입을 써주는 것으로 해결.

함수포인터 전달 관련 오류인 C3867 에러 백개 정도는 단순히 & 을 붙여주는 것으로 해결.

그리고 제일 짜증나는 std 오류 백만개.

std에서 stdext로 옮겨가버린 stl의 자제 분들은 변환 작업으로 손쉽게 변환 되었지만 문법 자체가 변해버린 경우는 혹시 잘못 작동 할까봐 쉽게 수정이 조심스러워졌다. 쳇. 그리고는 시간 관계상 포기.

그리고 나서 확인해보니 Visual C++ 2005 컴파일러의 주요 변경 사항을 보니 이제 안되는게 참 많구나.. 라는 생각이 든다.

조만간 날 잡아서 오류들 전부 해결 하고 아무도 모르고 한번 팀에 바이너리 배포 해봐야겠다. 아무도 이상한 점을 발견 하지 못한다면 정상적으로 포팅 한거겠지..

아 이런것 좀 누가 와서 걍 해줬으면 좋겠다.




--
Name
Password
Homepage
Secret
[Yuno.org, 2009/04/12 05:58, Programming]


NSIS ( Nullsoft Scriptable Install System )을 사용해서 소프트웨어를 패키징 & 배포를 할때 비스타에서 문제점이 발생한다. 물론 배포 전에 각 OS 별로 테스트를 진행하지만 어떤 조건이 갖추어진 경우에만 티가 나는 경우가 있어서 짜증을 불러 온다.


모든 문제는 Vista의 UAC ( User Account Control )에서 부터 시작 되는 문제이다. Microsft가 Vista를 출시 하면서 기존에는 그다지 신경 쓰지 않던 사용자 계정 간의 보안 문제를 적용하기 시작했다. 즉 계정 별로 시스템에 큰 영향을 줄지 모르는 것들에 대해서 제한적으로 실행을 허가 하는 기능을 추가 한 것이다.

프로그램을 설치 할때 일반적으로 시스템 정보에 접근해서 레지스트리, 유저별, 전체, 단축 아이콘, 바탕화면 아이콘 등을 작업하는 설치 프로그램 역시 UAC의 영향을 받게 되어 버린것이다!


현재 리포트 되어 있는 대표적인 2 가지 문제는 전부 UAC 서비스를 사용하지 않는 상태에서는 문제가 전혀 발생 되지 않는다.

첫번째 문제, Vista에서 대용량 실행 파일을 관리자 권한으로 실행하면 UAC 의 영향을 받아서 소프트웨어 구동 시간이 매우 오래 걸린다. ( 소니 TZ 노트북에서 200MB 짜리 단일 NSIS 설치 파일 실행시 약 20초, 1.5GB 짜리 실행시 약 1분 이상, 거의 10MB당 1초의 구동 대기 시간 소요 ) 결국 이것은 사실상 비스타의 버그!!!!!

이 문제는 예상되는 바로는 UAC가 실행 되는 파일을 전체 검사를 하여 인증서와 같은 것을 검색 하는 것으로 보인다. (관리자로 실행 하기 위해서 manifest 파일 같은 것을 응용 프로그램에 포함시키기도 하기 때문에)

두번째 문제, Vista에서 User 권한으로 프로그램을 설치 하려 하면 관리자 권한 (Administrator )의 폴더에 접근을 할 수 없으며 단축 아이콘 및 레지스트리에 접근이 불가능하다.


아쉽게도 첫번째 문제는 아직 해결 방법이 없다. NSIS 에서 컴파일을 할때 RequestExecutionLever 을 User 로 설정해서 실행 권한을 낮추면 문제 없이 정상적인 속도로 실행이 된다. 하지만 이 경우에는 바로 두번째 문제에 봉착 하게 되어진다. -_-

첫번째 문제를 해결 하는 제일 좋은 방법은 설치 파일을 분할 하는 것이다. 이것은 NSIS에서 분할 파일 배포 방법( http://www.yuno.org/295 ) 을 이용하면 된다.

두번째 문제는 NSIS의 UAC 플러그인을 사용하면 된다. UAC Plugin은 사용자 권한(USER LEVEL)로 실행 되었을 경우 내부에서 해당 실행 파일을 다른 프로세스를 이용하여 관리자 권한으로 다시 한번 실행 시켜주는 방식을 통해서 두번째 문제를 해결 하고 있다. 하지만 첫번째, 두번째 문제가 엮인 경우 두번째 문제를 해결 하기 위해 UAC 플러그인을 사용하면 다시 첫번째 문제로 돌아가게 된다는 것을 명심하자. ( 쪼개는 방법 밖에 없단 이야기 )

또한 UAC 플러그인은 유저단의 아이콘 만들기 라던가, 유저 레벨로의 별도 실행 파일 실행 등의 기본적인 기능을 포함하고 있다.  만약 두번째 문제만 겪고 있을 경우는 UAC Plugin으로 가볍게 문제를 해결 할 수 있다.

이것과 관련된 NSIS Forum의 thread가 있으니 한번 읽어 볼만하다.


--
Name
Password
Homepage
Secret
[Yuno.org, 2008/11/02 02:19, Programming]


소프트웨어가 중복 실행 되지 않게 하기 위해서 사용하는방법. 몇가지 방법이 있다.

온라인 게임 클라이언트들이 대부분 이 방법들을 사용하고 있다. 따라서 멀티로더와 같은 것을 만들때 대부분 별도의 디버거를 어플리케이션에 붙여서 관련 함수들을 찾아서 사용한다. ;;

아무튼, single instance를 위한 작업이라면 그냥 아에 알려진 방법을 전부 다 섞어서 사용해도 될 것 같다. -_-..
그러면 멀티로더를 만드는 사람이 '한가지'를 발견해서 수정해도 작동 되지 않음을 알고 포기 할 수도 있고 (가능성 낮은가-_-).. 최소한 작업시간을 10초라도 더 증가 시킬 수 있으니 ...

사실 대부분의 방법들은 그 목적을 위해서 만들어 졌다기 보다는 다른 용도로 만들어진 것들이지만 그것들을 활용해서 이러한 효과를 볼 수 있는 것이다. 예를 들어 뮤텍스나 세마포어, data_seg 같은 것들은 쓰레드간의 데이터 공유를 위해서 존재 하는 것들인데 이것들을 활용 하는거다. 만세!

뭐 암튼, 뮤텍스와 data_seq의 예제를 대충 남겨둔다. FindWindow야 워낙 알려진 것이니까 스킵.

아.. 그리고 요즘은 별도의 보안 프로그램(HackShield, GameGuard)을 이용하기도 한다.

Mutex

#ifdef _SINGLE_INSTANCE
  Char  sMutexName[ MAX_PATH ];
  ::_stprintf( sMutexName, _T( "[ApplicationName].SingleInstance" ) );
  this->hSingleInstanceMutex = ::UNICreateMutex( NULL, YES, sMutexName );
  if( ::GetLastError() == ERROR_ALREADY_EXISTS )
  {
   if( ::WaitForSingleObject( this->hSingleInstanceMutex, 5000 ) == WAIT_TIMEOUT )
   {
    ::exit( 0 );
   }
  }
#endif


#pragma data_seg()

#define _INSTANCE_NAME  "[Applicatipn].SingleInstance"
#pragma data_seg(_INSTANCE_NAME)
DWORD   _InstanceCount=0;
#pragma data_seg()
#pragma comment(linker, "/section:" _INSTANCE_NAME ",rws")


_InstanceCount++;
if ( _InstanceCount > 1 )
{
   ::exit( 0 );
}


아 사실 자세히 전부 다 쓰려고 했는데..
귀찮다...



--
Name
Password
Homepage
Secret
[Yuno.org, 2008/09/09 00:35, Programming]

말랑양이 원해서 한시간에 걸쳐서 만들어 본 것

티스토리와 태터툴스에서 RECENT COMMENT에서 자기 이름으로 달린 COMMENT는 보이지 않게 하는 사이드 바 스킨.

태터툴스는 코드를 고치면 쉽게 되지만 티스토리는 코드 수정이 안되므로 스킨을 수정해서 자바 스크립트를 이용해서 핸들링.

다만, 단점은 출력 갯수가 5개 일 경우는 자기가 5개 달면 자기가 단 5개가 출력 되니까 아무것도 나오지 않게 된다. 그래서 최대 출력 갯수 (티스토리는 30개)를 출력 하게 해 놓고 스킨에서 5개만 출력 하게 강제 수정.

그러면 자기가 최소한 25개의 리플을 최근에 달지 않는한은 5개는 남의 것이 나온다는..;;

자세한건 사용하는 말랑양이 자세히 써주겠지..;

스킨 코드 보기



--
Name
Password
Homepage
Secret
[Yuno.org, 2008/08/02 00:58, Programming]

NSIS(Nullsoft Scriptable Install System)는 어느새인가 국내 배포 프로그램에서 나름 차지 비율을 높여만 갔다. 아직 해외에서 발매되는 주요 상용 소프트웨어는 Install shield를 쓰고 있지만 전 세계의 수 많은 공개 프로그램들은 NSIS를 사용하고 있다.

우리도 꽤 오래전에 Install Shield를 이용해서 배포를 하다가 Install Factory로 바꿨었고 지금은 NSIS를 사용을 하고 있는데 최근에 배포 패키지의 용량이 2GB를 넘어버렸다.

nsis script를 이용해서 컴파일을 하는데 다음과 같은 에러가 나왔다.

Internal compiler error #12345: error mmapping file () is out of range.

Note: you may have one or two (large) stale temporary file(s)
left in your temporary directory (Generally this only happens on Windows 9x)."


뭐 대략 이런 메세지.

처음에는 파일 시스템의 문제인줄 알았다. 그리고 생각하니 NTFS를 쓰는데.. 단일 파일이 2GB를 넘는다 해도 문제가 없을텐데?라는 생각이 들고 하나씩 뜯어 나가니.. 아쉽게도 NSIS는 대용량 배포, 즉 2GB 이상을 공식적으로 지원 하지 않는다.

패키지 파일이 2GB 이상일 경우는 그다지 많지 않다. 결국 NSIS의 패키징 방식을 조금 바꾸어서 분할 배포를 해야 한다. 하지만 아쉽게도 NSIS는 공식적으로 분할 패키지 파일을 지원하지 않는다. 따라서 별도의 편법을 이용해서 배포 패키지를 만드는 수 밖에 없다. ㅠ_ㅠ.

어떤 방법이 있을까 곰곰히 생각해보고, nsis forum에서도 검색을 해보고, google도 좀 해보고..

결국 방법은 2가지로 압축 되었다.

첫번째 방법은 CAB으로 배포 데이터를 분할 압축하고 NSIS는 CAB 데이터를 풀어주고 프로그램 등록 및 레지스트리 등 각종 배포후 작업을 진행 하는 것.

관련한 정보는 http://nsis.sourceforge.net/CABSetup_plug-in 에서 관련 플러그인 자료를 구할 수 있다.

두번째 방법은 7zip (7z) 방식을 이용하는 것이다.

처음에는 더 친숙한 CAB 방식을 선택 했지만 이 녀석과 NSIS를 묶는 것 자체가 더 짜증났다. 한참을 준비하다가 훨씬 더 간단하게 만들 수 있는 7zip 방식으로 급 선회. 이 녀석은 lzma 방식으로 매우 높은 압축 효율율을 자랑한다. ZIP 보다 높은 압축률을 자랑한다. NSIS도 lzma 방식을 사용한다.

http://www.7-zip.org/ 에서 SDK와 인스톨 버젼을 배포 한다. 이 인스톨 버젼에 shell용 압축 해제 프로그램이 포함 되어 있다. 이것을 이용해서 NSIS SCRIPT의 외부 명령 실행 명령을 이용해서 설치 도중에 함께 배포한 데이터 파일을 배포 하는 것이다.

GUI 프로그램까지 함께 배포 하고 있으므로 정말 손 쉽게 일반 압축 프로그램을 사용하는 것 처럼 설치 하고자 하는 풀 인스톨 파일을 분할 압축 또는 단일 압축을 하고 NSIS 스크립트에서는 7zip sdk를 이용해서 만든 별도의 프로그램 또는 함께 배포 해주는 압축 해제 프로그램을 포함해서 단순히 압축을 해주는 것이다.

매우 쉬워서 기존의 스크립트를 새 스크립트로 변경 하는데 10분도 걸리지 않으며 NSIS의 고통스러운 점인 단순히 스크립트의 내용 수정으로 인해서 엄청난 압축 시간을 요하는 매번의 컴파일을 거치지 않아도 된다는 것이다.

자세한 스크립트 설명은.. 나중에 사무실에서 시간이 나면 올려야겠다 ;;

어쨋든, 이리 저리 하여 NSIS 2GB의 저주에서 벗어났다. 만세에~





--
09kim | 2008/08/06 15:52 | PERMALINK | EDIT/DEL | REPLY
잘 했다 치타
쪼꼬 | 2008/08/08 00:40 | PERMALINK | EDIT/DEL | REPLY
잘 했다 치타(2)

으하하하 - -v
ㅜㅜ | 2009/11/08 12:39 | PERMALINK | EDIT/DEL | REPLY
2GB가 넘어가는 인스톨러를 만들다보니 저도 저런에러가뜨는데 정확히 어떻게 하는건지 알려주시면 감사하겠습니다 ㅠㅠ 사무실에서 시간나면 올리신다더니 1년이 지나도 안올려주시내요 ㅠㅠ
Name
Password
Homepage
Secret
[Yuno.org, 2008/06/17 23:32, Programming]

Visual Studio 2003을 쓰고 있기 때문에 만약 Visual Studio 2005 나 Visual Studio 2008에서는 이러한 문제가 없을지도 모른다. 하지만 난 오늘 Visual Studio 2003 때문에 고생을 좀 했다.

게임에 들어가는 UI 관련 그래픽 데이터를 별도의 툴 (아하 Skin Editor)에서 작업을 한다. Skin Editor에서 작업한 데이터는 바이너리 파일로 변환되어 Windows의 각 윈도우와 예하 컨트롤 처럼 바이너리 구조로 저장 된다.

그리고 저장된 바이너리 데이터의 구조를 게임 클라이언트에서 로드 할 수 있도록 별도로 클라이언트 코드에서 선언 할 수 있도록 enum 구조를 뱉어낸다. 클라이언트 프로그래머는 이것을 각 컨트롤 또는 윈도우의 클래스에 첨부 함으로써 클라이언트에서 UI를 윈도우 개념으로 핸들링 가능하게 된다.

그런데...................... 이건 뭥미? -_-

오늘도 새 UI 작업을 완료해서 저장을 하고 저장을 하고 컴파일을 하고 실행 하니 대뜸 나는 오류..

"더 이상 실행할 코드가 없습니다!" 응? 응? 응? 응? 그럼 니 뒤에 줄 서 있는 백만줄은 뭔데? 주석이냐?

...그때부터 싸움은 시작 됐다. 스킨과 관련 된거라는 경험에 의해서 확신이 들고 있었으므로 혹시 스킨을 핸들링 하는 클라이언트 코드에 Over Flow가 있는지 코드에서 변수와 각 메소드의 파라미터를 하나씩 까보기 시작했다.

없었다.

그렇다면 엄청나게 많기는 하지만 에러가 나는 부분이라고 생각 되는 몇 곳에 Break Point를 살며시 놔두고 코드를 따라가기 시작, 상위 Window 개념중에 하나인 Holder Count가 실제 Holder Count와 데이터 바이너리에서 로드한 Holder Count가 달라서 생긴 문제라는 사실을 확인. 일단 데이터 오류를 의심하고 다시 에디터를 통해 저장 해보았지만 역시나 이상 무.

젠장!

에디터 소스를 열고 에디터에서 저장되는 구조에서 문제가 없는지 확인했다. 역시 여기서도 모든 변수들이 충분한 크기를 예상하고 만들어져 있었다.

대체 뭥미?!

데이터를 Hex Editor에서 열어서 확인 해 볼까? 하는 고민중에..

문.득. 정말. 그냥 문.득.

전체 컴파일을 해보고 싶었다.


그리고 약 15분후.

이런 .................................

링크 하다가 오류가 난거던지, 아니면 일부 코드의 변화 여부를 파악 못해서 목적 파일이 예전 것임에도 불구하고 목적 파일을 생성 안해서 논리 오류가 난 것인지. 알 수는 없다. ( 후자라고 예상 하고 있다 )

하지만, 어쨋든 새 목적 파일을 새로 다 생성하고 난 후에 링크 한 바이너리는 에러 없이 쌩쌩 작동 되었다.

흑.

앞으로는 종종 '솔루션 전체 다시 컴파일' 버튼을 사랑해주어야 겠다. ㅠ_ㅠ.



--
육식동물 | 2008/06/18 09:39 | PERMALINK | EDIT/DEL | REPLY
하루에 10번이상 리빌드합니다.;;
특히 enum이나 define가 변할경우.. 잘 인식못합니다.
그래서 인크래드빌드를 쓰는데
인크래드빌드는 잘인식해서.. 사용되는 모든 소스를 빌드하는데..

VS 는.. 하나만 빌드합니다(;; 가끔다하기도하는데.. 소스가많아지면 찾지못하더군요..)
aaaa | 2008/06/18 13:02 | PERMALINK | EDIT/DEL | REPLY
인크리드빌드도 똑같은 현상의 버그가 있습니다. ^^
최재규 | 2008/06/18 16:04 | PERMALINK | EDIT/DEL | REPLY
저도 그런 경험이 있습니다. 그래서 항상 배포할 실행파일은 Rebuild All 을 하죠.
주노 | 2008/08/06 11:14 | PERMALINK | EDIT/DEL | REPLY
진짜 심각해 보이는 문제가 발생했는데.... 1-2시간 고민한 적도 많죠..^^
그러다 뤼빌드올!! 해결되면 욕나와요 ^^
2005쓰고 있는데.... 요즘 패치되서 덜 하긴 한데....
New Line Error 어쩌고 하는 것도 가끔 떠요.
에러나는 부분에서 엔터 한 줄 추가하면 빌드가 되더군요.
어차피 VS도 개발자들이 만들었는데... 버그 없겠습니까? ^^
그래도 수백만 줄 코드를 릴리즈해주는 것에 감사해야죠 뭐 ㅋㅋㅋ
Name
Password
Homepage
Secret
[Yuno.org, 2007/12/16 07:23, Programming]


게임 서버와 클라이언트에서 어떤 리스트(명단)을 주고 받을때 자료 구조를 만들어서 쓰기 보다는 주로 STL을 쓴다. 그중에서 많이 쓰이는 것들이 list와 vector인데, 이번에도 역시 서버에서 리스트를 받으면서 vector를 사용하였다.

뭐 워낙 클라이언트에서도 많이 쓰이고 있고, 해당 기능을 구현 하는 곳에서도 많이 쓰였기 때문에 별 생각 없이 코드를 작성, QA 도중에 이상한 문제가 발생 하기 시작했다.

구현된 기능중에 벡터 컨테이너에 저장된 구조체 배열 중에서 특정 값을 가진 아이템들을 전부 삭제 하는 기능이 있었다. 예를 들어서 유저 목록이라고 한다면 A라는 class id를 가진 모든 유저를 삭제 하는것과 같은 기능이다.

처음에 구현된 코드는 다음과 같았다.

iterator iterCur;  
iterator iterEnd;

iterCur = this->MemberList.begin();
iterEnd = this->MemberList.end();

for ( ; iterCur != iterEnd ; iterCur++ )
{
 if (iterCur->type == ipPacket->type) {
  this->MemberList.erase(iterCur);
 }
}

그런데 이 코드를 통해서는 정상적으로 기능이 구현 되지 않았다. 테스트 된 환경중에 2개의 데이터를 벡터에 넣어두고 둘다 지워질 수 밖에 없는 경우의 값을 대입시켰을때 조건이 명확함에도 한개만 삭제 되어졌다. VS의 디버거를 통해 알아본 결과 루프가 1회만 돌고 있기 때문이었다.

1회만 도는 원인이 반복자의 무효화 관계가 있을 거라고 생각하고는 erase 이후에 반복자를 다시 대입시켜 주는 코드로 변경해보았다.

iterator iterCur;  
iterator iterEnd;

iterCur = this->MemberList.begin();
iterEnd = this->MemberList.end();

for ( ; iterCur != iterEnd ; iterCur++ )
{
 if (iterCur->type == ipPacket->type) {
  this->MemberList.erase(iterCur);
  iterCur = this->MemberList.begin();
  iterEnd = this->MemberList.end();
 }
}

허나 이 역시 매한가지. 그리고는 곰곰히 생각해보았다. 그냥 벡터의 .size()를 통해서 루프를 돌릴까.. 하는 고민을 했으니 배열로 접근 할 경우 삭제가 불가능하기에 접고 저렇게 작동하는 원인을 찾기 위해 노력해 보았다. 그리고는 다음과 같은 결론을 내렸다.

일단 처음의 두 코드의 루프가 전부 돌지 않았던 것은 for 문 자체의 증감식문 때문이었다. 만약 처음의 첫 코드를 이용 할 경우 반복자의 무효화가 발생 할 경우 stl 내부에서 참조 오류를 내며 crash 되어버린다.

그것은 이미 무효화 되어 버린 반복자에 for의 증감식문이 영향을 줘서 그렇다. (처음 두 코드에서 for에 있는 iterCur++ 문) 따라서 루프 속에서 iterCur or iterEnd or iterEnd의 무효화가 일어날 경우를 대비해서 다시 대입 시켜 주어야 한다.

즉, 반복문 안에서 두가지 경우가 일어 날 수 있게 되는 것이다. 현재 반복문의 증감식으로 부여 받은 이터레이터가 유효한 경우는 지워지지 않은 경우이므로 증감식문을 이용하여 증감 시키고, 무효화가 일어나는 경우, 즉 삭제가 될 경우는 별도의 값으로 해당 이터레이터를 대입 시켜 주어 증감식문의 영향을 받지 않게 해야 한다.

하지만 만약 벡터가 삭제가 된 이터레이터 외에 앞 뒤 아이템의 위치 역시 변경 될 경우는 난감할 지도 모르겠다. (이런 경우가 있나?)

어쨋든 대략 이런 구조로 작성 하면 되겠다.

   iterBegin = this->MemberList.begin();
   iterEnd = this->MemberList.end();

   for ( iterCur = iterBegin; iterCur != this->MemberList.end(); iterCur = iterNext ) {

    iterNext = iterCur;
    if (iterCur->type == ipPacket->type) {
     MemberList.erase(iterCur);

    
반복문의 증감식을 이용 할 수 없으므로 별도의 값을 대입. 벡터 전체의 재정렬(전체 무효화)가 생기지 않는다면 루프의 증감식문의 영향을 받지 않은 정상 반복자를 별도로 저장 하고 해당 값을 대입해도 된다. 아래와 같이 begin을 대입하면 삭제가 이루어 질때마다 전체를 처음부터 다시 돌것이므로 성능 저하가 온다.

     iterNext= this->MemberList.begin();
    } else {
   
    
반복문의 증감식 대용
     ++iterNext;
    }

어쨋든, for의 증감식문을 전혀 생각 안하고 버릇대로 손이 갔다가 고생좀 했다 ;;

---------------------------------

아래 리플을 보고 알았습니다. -_-. visual assist 쓰면서 몰랐다니. ㅡㅡ;
추가 vector의 erase의 반환값이 있었나 봅니다 -_-. 반환값이 current iterator인가 봅니다~

iterCur = this->MemberList.erase(iterCur);

으로 삭제 된 후의 이터레이터를 받아 올수 있는거 같군요.




--
지나가다 | 2007/12/16 19:35 | PERMALINK | EDIT/DEL | REPLY
iterator iterCur;

iterCur = this->MemberList.begin();

while( iterCur != this->MemberList.end() )
{
if( iterCur->type == ipPacket->type )
{
iterCur = this->MemberList.erase(iterCur);
continue;
}

++iterCur;
}
Yuno | 2007/12/17 00:40 | PERMALINK | EDIT/DEL
오오 그렇군요

erase 가 반환자가 있었군요!
요원-X | 2007/12/16 21:51 | PERMALINK | EDIT/DEL | REPLY
오~ continue라는게 있었네요. 저도 제 코드들 보면서 약간 지저분하다고 생각했는데, continue를 쓰면 좀 더 깨끗해질거 같네요.
요와이 | 2007/12/18 13:53 | PERMALINK | EDIT/DEL | REPLY
http://lagoons.net/tt/599
그냥 remove 알고리즘에 함수객체 돌리는게 속편한거 같아요.
주노 | 2008/08/06 11:07 | PERMALINK | EDIT/DEL | REPLY
와우! 좋은 글 감사합니다.
비슷한 코드는 찾아서 적용하고 있었는데, 이유를 잘 모르겠더군요.
큰 도움 되었습니다. 감사합니다. ^^
Name
Password
Homepage
Secret
[Yuno.org, 2006/12/15 00:45, Programming]

이게 과연 Programming 분류에 들어가야 하나 싶지만. 아무튼.

웹은 그 태생의 한계 때문에 여러 시스템을 구현할때 다양한 편법이 이용되어진다. 처음에는 편법이었지만 시간이 지나갈수록 당연시 되어지고 그 헛점 조차 그 편리함에 덮혀지는 뭐 그런..

방금전에 뉴스 사이트를 보다가 이러한 기사를 보았다.

http://news.naver.com/news/read.php?mode=LSS2D&office_id=032&article_id=0000203799&section_id=102&section_id2=249&menu_id=102

대략 요약하자면 인터넷 쇼핑몰에서 별도의 결제 사이트를 연동하여 결제할때 주고 받는 통신을 위조해서 적은 금액으로 물건을 구매 하는 행위에 대한 이야기다.

이거를 처음 발견했던건 3년쯤 전이었다.

보통 대형 쇼핑몰이 아닌 일반 쇼핑몰들의 결제 시스템은 결제 대행 서비스를 이용한다. 또한 결제 대행 서비스 업체들은 자체 보안 때문에 쇼핑몰 서버에 별도의 모듈을 제공하는게 아닌 본인들이 제공하는 특정 페이지를 연결해서 관련 정보를 받아서 처리하고 해당 결과를 쇼핑몰 호스트로 다시 넘겨주는 작동 방식을 가진다.

이 문제는 결국 쇼핑몰의 결제 시스템은 결제 여부를 대행 업체의 결제 시스템에 의존하게 된다는거다. 두 호스트는 물리적으로 연결 되어 있지만 단일 랜 선이 아닌 인터넷을 넘나드는 공개된 패킷에 의해서 주고 받게 된다.

이는 쇼핑몰 솔루션의 호환성과도 직접적 관계가 있기 때문에 일반적으로 (지금은 어떨지 모르겠지만) GET, POST 와 같은 단순 전송 방식을 사용한다. 차라리 서비스나 데몬이 돌면서 TCP/IP 를 통한 직접 통신이면 나을지도.

아무튼, 그러한 통신은 결국 한번이라도 그러한 시스템을 구축해보거나 시스템 구조를 아는 사람에게는 허약하지 그지없다.

대표적이로 두가지 취약점이 여기서 들어난다.

1. 쇼핑몰에서 대행 업체로 보내는 결제 조건 정보. 즉, 금액과 결제 방식 등의 정보의 공개 문제
2. 대행 업체에서 결제 완료후에 쇼핑몰로 결과를 전송할떄의 문제

이 두가지 문제는 모두 사용자(클라이언트. 여기서는 브라우저)를 거친다는것에 있다.

이중에 제일 쉽게 접근이 가능한 첫번째 문제는 매번 우리가 결제할때 쇼핑몰에서 결제 정보를 브라우져에 특정 URL에 특정 파라미터(위의 결제 정보)를 가지고 열도록 명령하고 그 정보는 사용자 브라우저에 그대로 남은 상태로 해당 페이지로 가게 되는거다.

즉, 해당 페이지를 열때 넘어오는 파라미터를 변경하면 결국 그 파라미터대로 페이지가 열리게되고 이는 위의 기사에서 나온 것 처럼 금액의 변경으로 쉽게 이어진다. 결국 대행 업체의 솔루션은 받은 금액 그대로 (변경 여부는 알 수 없으므로) 결제를 하게 되고 그 결과를 쇼핑 솔루션에 통보 하게 되는거다.

여기서 결국 쇼핑몰 솔루션을 개발한 사람의 완벽성에 영향을 받게 되는데 어지간한 대행 업체는 결과를 보낼때 대략 요청한 결제 번호 (주문 인덱스 넘버와 같은 인덱스 넘버), 금액, 결제 정보 등을 넘겨준다.

결국 이곳에서 결제 번호(인덱스)만으로 결제 여부를 처리 해버리면 백만원짜리를 만원을 결제 했든, 십만원을 결제 했든 해당 주문번호의 결제 여부는 처리가 되어 버리고 완료 처리가 되어 버릴것이다.

이것 저것 크로스 체크를 하는 개발자라면 돌아온 결제 정보의 금액까지 확인 해서 크로스 해야 할 것이고 2번의 문제 역시 막기 위해서 해당 정보를 전송한 호스트의 주소 역시 크로스 체크 해야 한다. 물론 이것도 작정을 하고 스누핑 한다면 대책이 없겠지만 -_-

어쨌든 가급적 결제 시스템과 같은 예민한 시스템은 클라이언트에서는 입력만 받고 모든 전송 및 처리는 호스트에서 처리 하는게 제일 안정적이다.

쩝.

저 기사를 보니까 그때 내가 테스트 했던 10곳의 쇼핑몰중에 저 방법이 통하지 않았던 곳은 단 두곳밖에 없었다는 기억이 다시 새록 떠 오른다.

난 차마 지르지는 못했는데 ...



--
Name
Password
Homepage
Secret
[Yuno.org, 2006/11/22 12:31, Programming]

게임 케릭터 미리 보기 작업을 하느라 처음으로 ASP.NET C#을 이용해서 그래픽 파일을 브라우저로 전송하는 코드를 작성할 일이 생겼다.

ASP.NET을 처음 만져봐서 각종 정보를 찾아 보니 든든한 클래스가 많이 존재했다. Bitmap, ImageConvert, Color 등..

따라서 게임 그래픽 데이터 파일을 로드하여 Bitmap 에 넣고 각종 변환 작업 (색 변경, 조합, 이미지 머지 등) 수행 후에 BMP로 저장 또는 Response.OutputStream으로 바로 이진 전송을 해도 오류가 나는게 아닌가.

오류도 당황스럽게 GDI+ 일반 오류. (A generic error occurred in GDI+) 가 발생 하는게 아닌가..

뭐가 문제란 말이냐!! GIF나 JPG로는 잘 저장이 되는데! 심지어 파일로도 저장이 잘 되는데 BMP나 PNG, TIFF 등 이미지 손실이 없을 것만 같은 것들은 모조리 저장이 안된다니!?

한참을 고민하다가 해결 방법을 찾았다. 바로 목표 스트림으로 출력하는게 아니고 별도의 메모리 스트림을 거쳐서 찍으니까 모든게 해결. ... 쳇;

뭔가 별도의 포멧으로 저장 할때는 스트림에서 읽었다 썼다를 반복이라도 하는건가!?

------------------------------
  Bitmap Image;

  Image = new Bitmap (320,240);

  Image에 대한 그래픽 처리 blah blah..

  Response.Clear();
  Response.ContentType="image/bmp";
  Image.Save( Response.OutputStream, ImageFormat.Bmp);
  Image.Dispose();

- 출력 오류 GDI+ 일반 오류 발생.

------------------------------

  Bitmap Image;
  MemoryStream memStream = new MemoryStream();

  Image = new Bitmap (320,240);

  Image에 대한 그래픽 처리 blah blah..

  Response.Clear();
  Response.ContentType="image/bmp";
  Image.Save( memStream, ImageFormat.Bmp);
  memStream.WriteTo( Response.OutputStream );
  Image.Dispose();

- 성공



--
군계무학 | 2009/11/04 14:59 | PERMALINK | EDIT/DEL | REPLY
Response가 어떤변수인지 궁금합니다.
Name
Password
Homepage
Secret
[Yuno.org, 2006/10/20 22:52, Programming]

필자가 처음에 WEB을 접했던건 아주 오래전이다. 아직 VT 기반의 통신이 주였고 많은 사람이 VT 기반의 통신을 시작하기 시작할때 였다. 당시에 두산에서 서비스 하던 인터피아라는 유료 계정 서비스를 이용하여 처음으로 UNIX SHELL을 접하게 되었고, 그 이후에 ppp 또는 slip 서비스를 이용해서 처음으로 WEB을 접했을때는 정말 놀라웠다.

단순히 TEXT 기반의 통신에서, 아니 활자 만으로 이루어져 있던 텍스트 북에서 삽화가 함께한 책을 처음 발견 했을때의 놀라움 정도랄까? 이미지와 함께 볼 수 있는 인터넷 문서라니! 하지만 그 이상도 그 이하도 아니었다. 아직 세상은 Client Side에서 작동되는 어플리케이션이 대세였고, 온라인은 텍스트 기반이었으며 당시에 접한 WWW은 나에게는 단지 그림책일 뿐이었다.

언제부터인가? VT 통신이 정점을 찍고 하향 곡선을 그리기 시작했다. 그리고 발전 가능성이 깊다고 기대 되어지던 WEB 세상은 하나 하나 늘어나기 시작하고 VT 망의 10년에 가까운 데이터와 커뮤니티를 가진 업체들은 그 힘을 조금씩 잃어 가기 시작했다. 그때 까지만 하더라도 WEB 은 정적이었고 유저의 시스템에서 돌아가는 어떤 시스템들 보다도 사용자의 편리성은 결여 되어 있었으며 만약을 위한 준비 조차 힘들게 보였다.

벌써 상당히 오래쓴 테터 툴스이지만 몇일 전에 새 글을 포스트 하다가 우연히 이 에디터의 기능이 눈에 들어왔다. 지금까지는 별 생각 없이 사용했지만 그 기능들을 내가 인지 하고 나서는 놀라움에 사로 잡혔다.

아니. 단 6년만에 이렇게 놀라운 발전이 있었나?

그렇다. 웹은 끊임 없이 발전했다. Windows Application이 Windows 95가 나오면서 MSDOS의 TEXT 기반의 시스템에서 GUI 시스템으로 변경 되고 나서의 발전 만큼이나, 유저가 소프트웨어를 직접 설치해서 사용하는 어플리케이션에는 절대 따라 오지 못할 것만 같았던 WEB이 이제는 Server Side에서도 충분한 처리를 하고 다양한 표현 방법을 가질 수 있게 구성된 HTML과 그것을 효과적으로 (물론 사용에는 조금 스트레스를 불러 오지만) 컨트롤 할 수 있게 해주는 Javascript 덕이다. (비록 Windows 에서는 재미를 보지 못한 Java지만 WEB 에서는 그 목적 이상을 달성한 Java에게 갈채를-_-)

큰 편리함이지만 큰 불편함이었던 마우스에 의존 하는 시스템, 즉 단축키 시스템에 의한 직접 호출 기능의 부족과 정적으로만 생각되어지던 이미 출판 되어 버린 문서와 같은 HTML의 동적 변환 ( HTML + JAVASCIPT 결합물인 Dynamic HTML), 어느 시스템에서도 동일한 환경을 보장하는 SSI 시스템까지.

이제 컴퓨터를 한다는 개념 자체가 온라인 상태에서의 어떤 행위를 이야기 할 정도로 그 의미가 변했다. 더 이상 오프라인, 사용자의 시스템에 국한 된 시스템은 더 이상 그 값어치를 지니지 못하고 모든건 옮겨 가고 있다. 아니 이미 거의 대부분이 옮겨져 버렸다. (이것은 10년 전에는 오프라인에서도 컴퓨터를 가지고 할게 많았지만 지금은 단 10분만 오프라인 상태에서도 컴퓨터로 할게 없다는 점에서도 알 수 있다 -_-)

아마도 이제 컴퓨터의 모든 시스템은 온라인 클라이언트화 될 것이고, Windows Application의 설 자리는 점점 잃어 갈 것이다. HTML과 Javascript 그리고 최근에 비약적 성장을 하고 있는 Flash 가 그 자리를 조금씩 대체 해 나갈 것만 같다.

DOS 시절 부터 유저 소프트웨어 프로그래머 였던 나로써는 조금씩 사라져 가는 과거의 향수와 더욱 더 편리하고 강력해지는 새 환경 변화속에서 묘한 기분을 느낄 수 밖에 없다..



--
Name
Password
Homepage
Secret
[Yuno.org, 2006/10/12 17:56, Programming]

구글(Google)의 R&D 센터가 한국에 생긴다. 조금이라도 IT나 인터넷, 프로그래밍.. 이런 이야기에 관심이 있는 사람이라면 이런 저런 이야기가 많이 듣거나 봤을 것이다. 구글의 사무실 분위기 사원 복지 정책 등을 보고 있자면 소프트웨어 엔지니어의 천국이라는 생각이 들 정도이다.

많은 사람들의 구글의 채용 정책에 관심이 많고.. 또 많은 언론에서 구글의 독특한 채용 방법을 기사에 올리고 있다. 그러던 중에 우연히 매일 경제에 포스트 된 기사를 볼 수 있었다. 구글의 입사 시험 문제 중에 하나 였는데 사무실 옆 자리에 있는 형이 관심을 갖고 있는걸 보고 나도 한번 보게 되었다.

해당 기사 보러 가기 (이곳을 누르면 해당 기사로 갈 수 있습니다.)

" 양수 n에 대해서 1과 n 사이에 1이 나오는 횟수를 나타내는 함수를 f(n)이라고 한다. 예를 들어 f(13)=6이다. f(n)=n이 되는 첫번째 양수는 1이다. 두번째 양수는 무엇인가. "

풀어서 이야기 하면 양수 N 까지의 숫자를 나열 했을때 1 이 들어간 수를 헤아리는데 양수 N까지의 1의 갯수가 양수 N과 동일한 두번째 값을 찾는 문제이다.

단순하게 N까의 루프에서 1의 숫자를 헤아리게 만든다면 P4 3G 라도 엄청난 시간이 걸린다. -_-

한번쯤 관심이 있다면 풀어 보자~

<< 풀어본 답 열기 >>



--
alklid | 2006/10/12 22:23 | PERMALINK | EDIT/DEL | REPLY
ㅋ 전 못가겠네요..-_-;
superkkt | 2006/10/17 09:18 | PERMALINK | EDIT/DEL | REPLY
저는 이력서도 못내밀겠네요.. 도대체 뭔말이여~^^
xevious7 | 2006/10/20 23:32 | PERMALINK | EDIT/DEL | REPLY
유노님 포스트는 잘 보았습니다만 ,시험문제를 잘 풀려면 문제의 의도를 파악하는게 중요하다고
생각합니다. 이 문제의 의도는 다른데 있는 것 같습니다.
유노님의 코드는 유노님의 설명과 달리 어찌되었는 while 문 안에서 ++n 를 하기 때문에 n번의 수행이 필요합니다.
n번을 수행하는 코드는 대부분의 프로그래머가 쉽게 작성가능합니다.
그 안의 최적화하고 별도의 문제로 n번을 수행해야 합니다. 즉 복잡도가 n이라는 것입니다.
만약 100만번째 숫자였다면 100만번을 돌려야 하는 것이지요.
http://bbs.python.or.kr/viewtopic.php?t=22323 결국 이코드랑 비교하자면
유노님이 최적화 한부분은
1의 검색부분인데 , 이것은 이 시험문제가 의도한 것이 아닌 것 같습니다.
시험문제를 낸 사람이 원하는 것은 n번 돌리는 즉 복잡도 n의 프로그램을 원하는것이
아닌 것 같습니다.
복잡도 n 을 줄여나가는 것이 목표인것 같습니다.
적어도 마지막에 말한 좀더 가속하고자 하는 부분
의 라직을 다듬어 문제의 답을 작성하셔야 될듯 합니다. ~ 초면에 실례가 되었습니다만
도움이 도움이 되고자 적어보았습니다.
Yuno | 2006/10/21 00:13 | PERMALINK | EDIT/DEL
아아 xevious7님의 말씀이 맞습니다. 다만, 저 문제를 푸는 모습을 보고 x까지의 정수에서 1의 출연 횟수 구하는 방식을 줄여 보고자 했기 때문에 저 결과물이 나온겁니다~ ;

저 같은 경우는 간단한 방식으로 연산 횟수를 크게 줄여놨었습니다. shift 를 이용한 x값의 증감을 이용했는데 이는 x와 f(x)가 항상 동시에 증가 한다는 전제를 기준으로 작업을 했습니다만.. 퇴근시간이라 작성은 중단했습니다만-_-;

아무튼 조언 감사드립니다 ;)
xevious7 | 2006/10/21 11:00 | PERMALINK | EDIT/DEL | REPLY
아 그러셨군요 ~ ^^ 역시 ~ 좋은 주말되세요.
rotoRl | 2006/12/03 16:10 | PERMALINK | EDIT/DEL | REPLY
이거 프로그램 돌리면 199980 나오는데여???
답은 199981 인데 뭐가 잘못된건가여???
초보 | 2007/04/27 06:31 | PERMALINK | EDIT/DEL | REPLY
죄송합니다만 도움 좀 주세요. 설명이 이해가 안되요

#include <stdio.h>


void main()
{

int N=0,C=1,D;
int Result=0;

while(C)
{
N;
D=N;

while( D )
{
if( D % 10 == 1){
Result =1;
}

D = D / 10;
printf("M, M, M\n", N, Result, D);

}



if( N == Result
seobi | 2008/06/17 16:42 | PERMALINK | EDIT/DEL | REPLY
저도 한번 한시간동안 끙끙대며 문제 풀어 봤는데요..
아무리해도 복잡도를 줄이는건 이방법 왜엔 없는거 같네요..
제가 푼 방법은 간단히 첫번째 자리가 2~9일때는 1의 갯수가 증가하는 n을 추월할수가 없으니 첫번째 수가 2로 시작하면 바로 다음자리 10^n 으로 넘겨버립니다..
10^n 일때 1의 갯수는 쉽게 계산이 되더라구요..
소스는 좀더 다듬으면 줄어들긴 하겠지만 남이 보기엔 이게 가장 좋아 보이는군요..

사실 while문 안에
do {
if( jari_check%10 == 1 )
s_count++;
}while((jari_check = jari_check/10) > 0);
count += s_count;
이것만 있으면 끝인데 복잡도를 줄이려니 전체 소스가 길어지는군요..
어쨋든.. 구글~ 들어간사람들은 부럽삼...
int n = 0;
int count=0;
int s_count;
bool check;
int jari, jari_check;
while( n > count || n <= 1 ) { //1의 갯수가 n보다 같거나 클때까지..
jari_check = ++n;
check = false;
jari = 0;
s_count = 0;

do {
if( jari_check < 10 && jari_check == 1) //첫번째 자릿수가 1인지 여부 판단
check = true;
else //총 몇자리인지 판단
jari++;
if( jari_check%10 == 1 ) //현재 숫자에서 1이 몇개 있는지 판단하여 기존 count에 더함..
s_count++;
}while((jari_check = jari_check/10) > 0);

if( !check ) { //첫번째 자릿수가 1이 아닐때.. 즉 20, 200, 2000 될때 바로 100, 1000, 10000 으로 점프..
int k = 1;
int tmp_sum = 1;
int tmp_count = 0;
while( k < jari ) { // 1의 갯수.. 100에 21, 1000에 301, 10000에 4001
tmp_count = pow(10, k++ );
tmp_sum = ( tmp_count + (tmp_sum*10) );
}
n = pow(10, k);
count = tmp_sum+1;
}
else
count += s_count;
}
printf("Result f(%d) = %d\n",n,count);
Name
Password
Homepage
Secret
[Yuno.org, 2006/09/30 11:35, Programming]

완료 된지 시간이 조금은 지난 프로젝트. 게임으로 따지면 서비스가 시작된지 조금 된 게임들. 프로그램으로 따지면 최초 개발 이후 고객에 따라서 커스터마이징을 하고 있는 과정 정도에 있는 경우에 해당한다.

어떤 프로젝트든지 완벽한 문서와 모든 코드를 숙지 할 수 있는 교육 과정이 있다면야 문제 없지만, 현실적으로는 그런 일은 드물다. 아니 있을 수 없다고 해야 할런지..

완성된 프로젝트를 이어 받아서 커스터마이징 및 유지 보수, 추가 작업을 하다 보면 가끔은 이런 기능이 있으면 좋을 텐데 하고 관련 자료를 찾아서 적용 준비를 하다보면 평소에는 보이지 않던 파일명과 클래스명이 보이곤 한다. 혹시.. 라는 마음에 찾아 보면 역시나 oTL.. 이미 구현이 되어 있지만, 코드 깊은 곳에 묻혀 있어 알 수 없었다던가 특수한 경우에만 작동하게 되어 있다던지 하는 일이 있다.

나름 난감하다. 그 기간동안 이런게 있다는 사실을 몰랐다니! 아쉬워 해봐야 소용 없다.. 하지만 다른 숨겨진 기능을 찾기에는 유지 보수에도 시간이 부족하다. 결국 프로젝트를 구성하고 있는 모든 구성요소를 모른채 계속 일을 이어 갈 수 밖에 없다.

oTL

이런 일은 가끔 예상치 못한 문제를 낳기도 한다.

예를 들어서 게임에서는 유저의 시야권에 다른 케릭터가 접근하게 되면 해당 사실을 서버에게 알려준다. 그런데 완성되고 나서 몇년이 지난후에 새 개발팀이 해당 프로젝트를 맡아서 진행하다가 이미 시야에 들어온 유저의 데이터의 갱신이 필요한 일이 생겼다.

그래서 작업 방법을 고민하다가 시야에 유저가 들어왔을때 해당 사실을 통보해주는 모듈을 사용하여, 같은 UserID를 가진 User Object가 다시 전송되면 업데이트 되는 방식으로 구현. 서비스를 한동안 진행하던 중에 우연히 코드중에 유저의 정보만을 업데이트 시켜주는 현재는 자주 사용되지 않는 패킷 모듈이 있었음을 발견 한다.

그런데 문제는 서버에서는 유저 데이터를 업데이트 시켜줄때 사용하는 정보와 유저가 시야에 들어왔을때 사용 되는 데이터가 동일할 것으로 예상. 공통적으로 유저 정보를 보내는 모듈을 사용하고 있었다.

어느 한쪽이 패킷 규약이 변경되면 다른 한쪽 역시 같은 모듈을 사용하므로 같이 변경 되는 그러한 방식.
그런데 서버 개발자도, 클라이언트 개발자도 이것을 모르고 있었다는거.. 결국 패킷은 데이터가 밀리는 현상이 발생. 특정 유저의 경우에는 예상치 못한 값에 의한 클라이언트 크래쉬가 일어나게 되었다. ;

난감..

한참동안을 원인을 못찾다가 이런걸 발견 하게 되면 정말 가슴이 아프다. 왜 조금 더 꼼꼼하게 살펴 보지 못했을까.. 하는 아쉬움은 이미 늦어 버렸으니까..



--
Name
Password
Homepage
Secret
[Yuno.org, 2006/09/30 03:14, Programming]

많은 프로그래머들이 겪고 있는 신비로움일까. 아니면 무지에서 나오는 결과일까.

내가 속한 팀에서는 대부분 사내 테스트이 경우에는 디버그 버젼의 클라이언트를 이용해서 사용한다. 더 많은 클라이언트, 케릭터 정보, 많은 로그들을 얻을 수 있다는 장점이 릴리즈 버젼의 클라이언트 보다 더 크게 작용하기 때문이다.

그런데 여기서 가끔 문제가 생긴다. 릴리즈 버젼의 바이너리와 달리 디버그 버젼은 탱크와도 같아서 정말 튼튼하다. 프로그래머의 가벼운 실수 쯤은 가뿐히 넘어가 버린다.

많은 프로그래머가 실수하는 배열의 인덱스 오류로 인한 오버 플로우 정도는 디버그 컴파일시에 생기는 패딩 효과에 의해서 무마 되어 버린다.

그런데 오늘 정말 거지 같은 일이 있었다.

Windows API를 사용하는데 같은 클래스의 같은 메소드에서 Windows API의 결과가 릴리즈와 디버그가 달랐다. 한시간 넘게 고민하고 고쳐보고 구글질을 해봤지만 결국 원인 규명에는 실패. 참 난감하다.

이렇게 한참을 한 가지 문제를 해결 못해서 끙끙 거리다 보면, 어떤 책의 구절을 찾기 위해서 책장에서 책을 하나 하나 꺼내서 뒤지다가 없으면 책을 내동댕이 쳐서 엉망이 되어버린 방 처럼 머리속이 엉망이 된다.

그럴때는 지우개라도 사용해서 머리를 깨끗하게 비우고 다시 시작하고 싶다.

그리고, 많은 경우가 잠시 바람을 쐬고 처음 부터 차근 차근 하면 해결 되기도 한다. -_-

하지만. 오늘은 실패했다. ㄴㅁ..



--
Remisa | 2006/10/13 02:20 | PERMALINK | EDIT/DEL | REPLY
그래서 저는 디버그도 릴리즈 모드로 한답니다. ^^;;
아무 정보도 없이 테스트 코드만 한참 짜다보면 실력도 늘거든요.. ㅁㄴ알먼아ㅣ;러ㅏㅣ;
Name
Password
Homepage
Secret
*1