SlideShare a Scribd company logo
1 of 75
온라인 게임에서사례로 살펴보는 Debugging NDC 2010 NCsoft 박일 http://parkpd.egloos.com twitter:rigmania
왜 디버깅인가?
디버깅과 섹스의 공통점 잘하면 재미있지만, 잘못하면 짜증난다. 하면 할 수록 늘지만, 너무 자주 하는 건 싫다. 밤늦게 할 때가 많다. 대놓고 얘기하진 않지만 남들은 어떻게 하는지 궁금하다. 교제가 거의 없다. 과정은 신경쓰지 않고, 어서 결론에 도달하려고 한다. 도구를 사용하면 도움은 되지만, 결국 사람이 해야 한다. 술을 많이 마시고 하면 다음날 어떻게 했는지 기억이 나지 않는다. 끝나고 나면 허무하고 담배가 땡긴다. 급할 때는 더 안 된다.
재현 진단 수정 및 반영
왜 재현부터? 버그가 나타날 때의 프로그램 상태를 볼 수 있다. 버그를 수정했을 때, 정말 수정했는지를 증명할 수 있다. QA팀이 재현 가능해야 한다.
환경 만들기 재현할 때는 문제가 되는 환경을 전부 똑같게 설정 파일, 이벤트 파일 확인, 하드웨어, OS 버전, 보안 프로그램 동작 여부 택배로 컴퓨터를 받아오기 해외에 설정 파일을 암호화해서 보내기 (3개월 전의) 해외 버전을 국내에도 유지하면 회귀 테스트 하기가 쉽다 이번 업데이트 이후 바뀐 것인지 테스트 가능
사례 - OpenMP 한 대의 컴퓨터에서만 에러 발생 알고 보니 특정 머신(하퍼타운4 cores)에서만 에러 발생. 이유는? 실제로 코드가 thread-safe 하지 않았음 제대로 MT 를 지원하는 머신 몰랐던 이유는? Core2 Duo 에서는 멀쩡함. 버그? 하퍼타운을 쓰는 다른 개발자는 설정에서 omp사용을 빼 놨기 때문에 에러 없었음
사례 보고! 현상은 원인이 있기 때문에 나타난다 정상적인 재현이 불가능하면, 억지로라도 재현한다 버그 report 를 그대로 믿지 마라 QA 에서도 아는 선에서 리포트를 쓴다 QA 분께 개인용 개발서버로 접속해서재현해 달라고 부탁한다 msn 과 사내전화 활용
사례 – 희귀 아이템 경매 라이브 서버가 아닌 테스트 서버, 그 중 한 npc에서만 발생 재현도안 되어서, 별 문제 없겠지 생각하고 무시 업데이트 후에 전 라이브 서버에서 문제 발생  이유 : 라이브 서버에서는 처음에 개발자가 직접 seed 값을 넣어줘서 경매에 문제 없었지만, 테스트 서버의 경우 개발자가 여러 npc중 한 npc만 까먹고 seed 값을 넣어주지 않았기 때문에 계속 문제가 있었음 처음부터 문제가 있었는데도, QA 에서는 ‘잘 되다가 저번 주부터 문제가 생겼음’ 이라고 보고했고, 개발팀도 QA 만 믿고특이한 사례보고라고 생각함 대규모 업데이트를 위해 모든 seed 값을 초기화했더니, 테스트 서버와 동일한 문제가 모든 npc에서 발생 [사례보고] 라는 제목 때문에 선입관 생김
사례보고를무시하면한 방에훅 간다
사례 – 공성과 결자해지 voidLoadData(){ // do something¡¦ CCastlec(nCastleNum);// dead code??? return; }
사례 – 공성과 결자해지 voidLoadData(){ // do something¡¦ CCastlec(nCastleNum);// dead code? NO!!! return; } classCCastle{ public: CCastle(intn){ g_CastleDB.Register(this); } };
사례 – 기계는 믿을 수 있는가 특정 머신, CPU, 그래픽카드, NIC
재현 진단 수정 및 반영
버그 찾기 dump 로 Crash 난 위치 확인 최근에 고친 파일부터 diff 이상현상이 생긴 시간대 근처 에러로그 확인 내가 고친 코드를 먼저 의심 다른 사람과 얘기해보자 피규어 디버깅 어셈블리는 마지막에 서버라면 실제 라이브 서버를 터미널 서비스로 들어가 작업관리자로 보기
Everybody lies false positive(거짓양성) 예전 바이너리를 쓰고 있다던가 false negative(거짓음성) QA가 고쳐지지 않은 걸 고쳐졌다고 한다 플라시보 효과 예전부터 있던 코드도 100% 믿지 말자 모든 걸 의심하자
Dump
minidump출력 Crash 이메일 전송 개발망에서도개발망email 로 전송 소스 컨트롤러에 날짜_Label 로 폴더 만든 후 바이너리, pdb를 저장 Symbol 서버 구축하기 장,단점
Stack 이 깨졌다면?
Base Line
필승교의 교훈
Base Line 지금 상태는 정상인가? 평소 CPU 는 몇 % 정도였나? 의도대로 최적화가 되었나?
Performance Counters Counter 를 log 나 DB 에 주기적으로 저장해 base line 를 만든다 counter 예시 SQL Server: SQL Statistics: Batch Requests/sec 초당 요청 받은 SQL 배치 요청 수 SQL Server: Buffer Manager: Buffer Cache Hit Ratio 90 이상이면 좋음 SQL Server: Locks: Lock Waits/sec 잠금대기요청수 Process: Page Faults/sec 프로세스가 Cache Hit하지 않은 페이지수
볼 수 있으면 고칠 수 있다
Visualizer (Visual Studio 2005)
Visualizer in C++ autoexp.dat으로 watch 창 변경 C:rogram Filesicrosoft Visual Studio 8ommon7ackagesebuggerutoexp.dat [AutoExpand] CMyData =head=<m_Head> m_Tail=<m_Tail,x> name=<m_Name,su> classCMyData{ public: CMyData(inth,intt): m_Head(h),m_Tail(t){} intm_Head; charm_Name[1024]; intm_Tail; }; int_tmain(intargc,_TCHAR*argv[]){ typedefvector<CMyData*>DataList; DataListdata; for(inti=0;i<10;++i){ data.push_back( newCMyData(i,i+1)); } return0; }
Debug Windows 1 {[function],[source],[module]} 뒤에location, variable_name, expression 특정 함수의 static local 변수 보기 void Test() { static intsLocalNum = 0; } : {Test,,}sLocalNum 특정 dll의 전역변수 : {,,foobar.dll}g_pMyStruct BP 걸어놓고 함수 실행하기 classCTest{ public: staticCTest&Inst(){ staticCTests; returns; } voidCheckValidate(){ OutputDebugString(L"T"); m_Test.push_back(1); } std::vector<int>m_Test; }; int_tmain(){ CTest::Inst().CheckValidate(); return0; }
Debug Windows 2 Pseudo Register @eax : 리턴값 @err : GetLastError @HANDLES 현재 프로세스의핸들 갯수 @ebp : 지역 변수시작 지점 @esp : 최상위 스택
사례 – Bot voidCPlayer::OnItemExchange( intnItemCount1,BYTE*pData1, intnItemCount2,BYTE*pData2) { for(inti=0;i<nItemCount1;++i){ // do something } for(inti=0;i<nItemCount2;++i){ // do something } }
Fuzzing Test 임의의 입력을 만들어 주는 Fuzzer 사용 Peach Fuzzing Platform http://peachfuzzer.com/ generation 과 mutation 으로 입력값 생성 RFuzz http://rfuzz.rubyforge.org 일종의 monkey test
Bug? (1.0<a.hP)=false (1.0>=a.hP)=false
Bug? (1.0<a.hP)=false (1.0>=a.hP)=false NaN(Not a Number) double answer = sqrt(-1.0);
structCData{ static const intHALF_NUM=0x7fffffff; static const intMAX_NUM=0xffffffff; CData():m_dPoint(1.0){ m_dData[0]=1.3;     m_dData[1]=1.5; m_nData[0]=HALF_NUM;  m_nData[1]=MAX_NUM; } voidApplyBonus(intnBonusIndex){ m_dPoint*=m_dData[nBonusIndex]; } doublem_dPoint; doublem_dData[2]; unsignedlongm_nData[2]; }; int_tmain(intargc,_TCHAR*argv[]){ CDataa; a.ApplyBonus(2); wcout<<L"isnan : "<<_isnan(a.m_dPoint)<<L''; wcout<<L"(1.0 < a.Point) : "<<(1.0<a.m_dPoint)<<L''; wcout<<L"(1.0 >= a.Point) : "<<(1.0>=a.m_dPoint)<<L''; return0; } // output isnan:1 (1.0<a.Point):0 (1.0>=a.Point):0 -1.#R, -1.#QO, -1.#QNB, -1.#QNAN (%.2~5f 로 출력했을 때의 결과)
사례 – 메모리 침범 classCTest{ public: conststaticintMAX_DATA=10; intm_Data[MAX_DATA]; vector<int>m_Nums; }; int_tmain(intargc,_TCHAR*argv[]){ CTestt; t.m_Nums.push_back(1); ZeroMemory(t.m_Data,sizeof(int)*CTest::MAX_DATA+10); t.m_Nums.push_back(1);// Crash return0; } #include <boost/array.hpp> int_tmain(intargc,_TCHAR*argv[]){ intcArray[256]; boost::array<int,5>aTest={1,2,3,4 ,5}; boost::array<int,256>aArray; cArray[256]=0;// not always die aArray[256]=0;// always die // Assertion failed: i < N && "out of range", file , line 91 return0; }
여러 가지가 정보다 에러 로그가 찍히는 주기 CPU 가 튀는 주기 로그에 찍힌 캐릭터의 위치와 시간 이렇게 빨리 이동했다는 것은? 개발자에게 GM 용 캐릭터를!
사례 – 언제 문제가 발생했나? 특정 시각? 특정 요일? CPU 가 튀는 주기는? 게임 서버가 새벽 2시만 되면 죽었던 이유는? Windows Update 가 새벽 2시에 실행 바이러스 update 창이 200 개 이상 오픈 같은 port 를 bind 계속하면 port 차단 서버관리툴이 실행될 때마다 특정 port 를 bind 하게 설계 일본 IDC 에서 꼭 설치하게 하는 패킷 필터링 시스템의 DDOS, Garbage Attack 탐지기가 해당 port 를 차단 얼마만에 죽는가 특정 tick 에 죽는 잘못된 코드와 memory leak Printf대신 사용한 로그 파일이 엄청나게 커짐 Memory leak은 아니지만, 너무 많은 메모리 할당 결국 일본 찾아가서 해결
재현 진단 수정 및 반영
가와사키(Kawasaki) 이야기 Kawasaki 의 제트 스키
가와사키(Kawasaki) 이야기 Kawasaki 의 제트 스키
가와사키(Kawasaki) 이야기 Kawasaki 의 제트 스키 새로 나온 제트 스키
해결책에는 여러 가지가 있다(있어야 한다) 펫, 소환수 자동 소환 09.09.09 라이브 업데이트 펫인벤 아이템을 언제 주인에게 옮겨줄 것인가? 진짜 옮겨야 하나?
로그 ,[object Object],너무 많은 로그는 노이즈+ 에러다 [NO_ERROR] 교훈 모든 로그는 unique 해야 한다 하다못해 __FILE__, __LINE__ 만이라도 ,[object Object],필요하면 id 와 item 클래스 아이디,심지어 캐릭터 이름 같은 경우 문자열로 남긴다 해외의 경우, 로그 접근을 직접 할 수 없거나 대응이 너무 느릴 수 있으므로 특히 주의
버그 기록 및 공유 버그 트래킹 툴에 FIX 할 때, 실제로 어떤 코드를 왜, 어떻게 고쳤는지 정보를 남긴다 누구보다 내가 나중에 그 정보를 필요로 하게 된다 일일회의 할 때 실수를 용기있게 공유한다 고참 개발자일수록 먼저 일일회의 내용을 각자 위키에 써 놓으면, 코드 변경 히스토리에서 버그를 만든 날짜에 내가 뭘 하려고 했는지를 알 수 있다 해결한 문제에 대해, 원인-해결책을 시간, 문제별로 정리해 놓으면, 몇 달 후 해외에서 같은 문제가 생겼을 때 빨리 해결할 수 있다.
좋은 코드 작성하기 voidTest1(CTest*p){ // do something } voidTest2(CTest&t){ // do something }
voidTest1(CTest*p){ if(p){ Test1_1(p); }else{ // do something } } voidTest1_1(CTest*p){ if(p){ // do something } } voidTest2(CTest&t){ Test2_1(t); } voidTest2_1(CTest&t){ // do something }
Source:  Coverity White Paper
버그의 비용 Source:  Coverity White Paper
버그 미리 찾기 _ASSERT !! Magic bit 사용 int 를 int64 로 바꾸면서 magic bit 끼워넣기 특정 bit 가 1 이 아니면 crash 정기적인 코드 리뷰 코드리뷰 별 거 아님 정적 분석툴과 CI 연동 일일빌드(TeamCity, CruiseControl.Net) Code Analysis pc-lint PMD Copy/Paste Detector
Code Analysis ,[object Object]
 포인터에 대한 사용 주의 경고, 중복된 변수 선언
 묵시적 Type Casting, sprintf 의 인자 개수 체크
단 x64 는지원하지 않으므로 편법을 좀 써야 함longlData[10]; sValue.Format("%d",lData[10]); warningC6201:Index'10'isoutofvalidindexrange'0'to'9'forpossiblystackallocatedbuffer'lData¡¯ voidCTest::DrawData(CDC*pDC){ ASSERT(pDC); pDC->FillSolidRect(rect,RGB(255,0,0)); } CRectrcTmp; for(...){ CRectrcTmp; }
PMD Copy/Paste Detector
단위 테스트
단위 테스트 적용 사례 사례 - 활 쏘기 활은 레이저 빔이 아니다 활은 포물선을 그리며 날아간다 그럼 이런 경우는?
해결방법 structTestBowData { 	Pos from; Pos to; bool expect; }; TestBowData data[] = { 	{ {10, 20, 10}, {100, 40, 50}, true},  // 성공해야 함 	{ {334, 13, 314}, {525, 11, 42}, false},  // 실패해야 함 	…. }; for (inti = 0; i < dataSize; ++i) { TestBowData& d = data[i]; 	_ASSERT(d.expect == TestCanShoot(d.from, d.to)); }
단위테스트간단한 팁
간단한 Mock 만들기 classCTest{ protected: intm_Test; voidTest(){} }; structCMockTest:publicCTest{ public: usingCTest::m_Test;// 부모 클래스의 멤버를 public 으로 쓰겠다. usingCTest::Test; }; int_tmain(intargc,_TCHAR*argv[]){ CTesta; //a.m_Test = 1; // protected 멤버 변수 접근할 수 없음. //a.Test();	// protected 멤버 함수 접근할 수 없음. CMockTest*pMockTest=(CMockTest*)(&a); pMockTest->m_Test=1;// CMockTest로 강제 캐스팅하면 접근할 수 있음. pMockTest->Test(); // a 가 CMockTest객체가 아니어도 이렇게 쓸 수 있다는 점에 주의 return0; }
Memory Leak Detector #define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1)) #define pHdr(pbData) (((_CrtMemBlockHeader *)pbData)-1) FILE*g_hfileLog=NULL; intAllocHook(intnAllocType,void*pvData,size_tnSize,intnBlockUse, longlRequest,constunsignedchar*szFileName,intnLine){ staticsize_tsizeAlloc=0; _CrtMemBlockHeader*pHead; if(nBlockUse==_CRT_BLOCK)// alloced by c lib returntrue; switch(nAllocType){ case_HOOK_ALLOC: sizeAlloc+=nSize; fprintf(g_hfileLog,"ALLOC%d",sizeAlloc); break; case_HOOK_REALLOC: break; case_HOOK_FREE: pHead=pHdr(pvData); sizeAlloc-=pHead->nDataSize; fprintf(g_hfileLog,"FREE%d",sizeAlloc); break; } returntrue; } int_tmain(intargc,_TCHAR*argv[]){ g_hfileLog=fopen("log.txt","w+"); fprintf(g_hfileLog,"Start"); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); _CrtSetAllocHook(AllocHook); fclose(g_hfileLog); return0; } #include <crtdbg.h> #define nNoMansLandSize 4 typedefstruct_CrtMemBlockHeader{ struct_CrtMemBlockHeader*pBlockHeaderNext; struct_CrtMemBlockHeader*pBlockHeaderPrev; char*szFileName; intnLine; #ifdef _WIN64 /* These items are reversed on Win64 to eliminate gaps        * in the struct and ensure that sizeof(struct)%16 == 0,  * so 16-byte alignment is maintained in the debug heap.        */ intnBlockUse; size_tnDataSize; #else  /* _WIN64 */ size_tnDataSize; intnBlockUse; #endif/* _WIN64 */ longlRequest; unsignedchargap[nNoMansLandSize]; // followed by: // unsigned char           data[nDataSize]; // unsigned char           anotherGap[nNoMansLandSize];  }_CrtMemBlockHeader;
Memory Leak Detector Memory Pool 대신 new, delete 를 쓰게 만드는 flag 를 하나 둘 것 이러면 LeakDiag, gflags, UMDH 로 버그 찾기도 훨씬 쉽다
단위테스트와업무 효율
개발자측정에는쓰지 말 것
결론 버그 찾는 법을 수련하자 어떻게든 재현하자 작은 버그도 무시하지 말자 쓰고 있는 툴을 최대한 활용하자 해결책을 최소 2 개 이상 생각해보자 버그를 미리 막을 방법을 만들어보자 단위테스트를 활용하자 서로의 경험을 공유하자
Q/A
Reference

More Related Content

What's hot

빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)YEONG-CHEON YOU
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델Seungmo Koo
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019devCAT Studio, NEXON
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규ChangKyu Song
 
게임 프로그래밍 기초 공부법
게임 프로그래밍 기초 공부법게임 프로그래밍 기초 공부법
게임 프로그래밍 기초 공부법Chris Ohk
 
게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPUYEONG-CHEON YOU
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018devCAT Studio, NEXON
 
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들영욱 오
 
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들강 민우
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012devCAT Studio, NEXON
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPSeungmo Koo
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스noerror
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012devCAT Studio, NEXON
 
모바일 게임 최적화
모바일 게임 최적화 모바일 게임 최적화
모바일 게임 최적화 tartist
 
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012devCAT Studio, NEXON
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018devCAT Studio, NEXON
 
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화Jaeseung Ha
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019devCAT Studio, NEXON
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현Bongseok Cho
 

What's hot (20)

빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)빌드관리 및 디버깅 (2010년 자료)
빌드관리 및 디버깅 (2010년 자료)
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규
 
게임 프로그래밍 기초 공부법
게임 프로그래밍 기초 공부법게임 프로그래밍 기초 공부법
게임 프로그래밍 기초 공부법
 
게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
 
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
 
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
 
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
양승명, 다음 세대 크로스플랫폼 MMORPG 아키텍처, NDC2012
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
 
모바일 게임 최적화
모바일 게임 최적화 모바일 게임 최적화
모바일 게임 최적화
 
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
전형규, 가성비 좋은 렌더링 테크닉 10선, NDC2012
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
 
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
 
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현
 

Viewers also liked

온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10Ryan Park
 
Programming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenProgramming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenRyan Park
 
AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8Ryan Park
 
즉흥연기와프로그래밍
즉흥연기와프로그래밍즉흥연기와프로그래밍
즉흥연기와프로그래밍Ryan Park
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.Ryan Park
 
나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10Ryan Park
 
나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까Ryan Park
 
Unicode 이해하기
Unicode 이해하기Unicode 이해하기
Unicode 이해하기Ryan Park
 
위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점Ryan Park
 
문자셋과 인코딩
문자셋과 인코딩문자셋과 인코딩
문자셋과 인코딩Jaehoon Jung
 
Domain Driven Design Ch7
Domain Driven Design Ch7Domain Driven Design Ch7
Domain Driven Design Ch7Ryan Park
 
Oop design principle SOLID
Oop design principle SOLIDOop design principle SOLID
Oop design principle SOLIDRyan Park
 
Oop design principle
Oop design principleOop design principle
Oop design principleRyan Park
 
NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅Seungjae Lee
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기Seungjae Lee
 

Viewers also liked (20)

온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
Taocp1 2 4
Taocp1 2 4Taocp1 2 4
Taocp1 2 4
 
Unicode
UnicodeUnicode
Unicode
 
Programming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenProgramming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. Raven
 
Unicode
UnicodeUnicode
Unicode
 
AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8
 
즉흥연기와프로그래밍
즉흥연기와프로그래밍즉흥연기와프로그래밍
즉흥연기와프로그래밍
 
카사 공개세미나1회 W.E.L.C.
카사 공개세미나1회  W.E.L.C.카사 공개세미나1회  W.E.L.C.
카사 공개세미나1회 W.E.L.C.
 
나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10
 
나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까
 
Unicode 이해하기
Unicode 이해하기Unicode 이해하기
Unicode 이해하기
 
위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점
 
문자셋과 인코딩
문자셋과 인코딩문자셋과 인코딩
문자셋과 인코딩
 
Domain Driven Design Ch7
Domain Driven Design Ch7Domain Driven Design Ch7
Domain Driven Design Ch7
 
Unicode100
Unicode100Unicode100
Unicode100
 
Oop design principle SOLID
Oop design principle SOLIDOop design principle SOLID
Oop design principle SOLID
 
Oop design principle
Oop design principleOop design principle
Oop design principle
 
NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅NDC14 - 사례로 배우는 디스어셈블리 디버깅
NDC14 - 사례로 배우는 디스어셈블리 디버깅
 
온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기온라인 게임 처음부터 끝까지 동적언어로 만들기
온라인 게임 처음부터 끝까지 동적언어로 만들기
 

Similar to 온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010

KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기Ryan Park
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10흥배 최
 
[2B2]기계 친화성을 중심으로 접근한 최적화 기법
[2B2]기계 친화성을 중심으로 접근한 최적화 기법[2B2]기계 친화성을 중심으로 접근한 최적화 기법
[2B2]기계 친화성을 중심으로 접근한 최적화 기법NAVER D2
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Testbeom kyun choi
 
100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7sung ki choi
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계Leonardo YongUk Kim
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018Kenneth Ceyer
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013Esun Kim
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?Kyoung Up Jung
 
김성훈 - 뛰어난 디버거가 되는 방법
김성훈 - 뛰어난 디버거가 되는 방법김성훈 - 뛰어난 디버거가 되는 방법
김성훈 - 뛰어난 디버거가 되는 방법성훈 김
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안Jeongsang Baek
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Ryan Park
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02정출 김
 
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기Jaeseung Ha
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 

Similar to 온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010 (20)

KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
 
About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
[2B2]기계 친화성을 중심으로 접근한 최적화 기법
[2B2]기계 친화성을 중심으로 접근한 최적화 기법[2B2]기계 친화성을 중심으로 접근한 최적화 기법
[2B2]기계 친화성을 중심으로 접근한 최적화 기법
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?
 
김성훈 - 뛰어난 디버거가 되는 방법
김성훈 - 뛰어난 디버거가 되는 방법김성훈 - 뛰어난 디버거가 되는 방법
김성훈 - 뛰어난 디버거가 되는 방법
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
 
HI-ARC PS 101
HI-ARC PS 101HI-ARC PS 101
HI-ARC PS 101
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02
 
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
[NDC2015] 언제 어디서나 프로파일링 가능한 코드네임 JYP 작성기 - 라이브 게임 배포 후에도 프로파일링 하기
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 

More from Ryan Park

OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.Ryan Park
 
프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장Ryan Park
 
UnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDUnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDRyan Park
 
Agile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowAgile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowRyan Park
 
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...Ryan Park
 

More from Ryan Park (6)

OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
 
Unicode
UnicodeUnicode
Unicode
 
프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장
 
UnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDUnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPD
 
Agile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowAgile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And How
 
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
 

Recently uploaded

캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionKim Daeun
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)Tae Young Lee
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Wonjun Hwang
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Wonjun Hwang
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Kim Daeun
 

Recently uploaded (6)

캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 

온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010

  • 1. 온라인 게임에서사례로 살펴보는 Debugging NDC 2010 NCsoft 박일 http://parkpd.egloos.com twitter:rigmania
  • 3. 디버깅과 섹스의 공통점 잘하면 재미있지만, 잘못하면 짜증난다. 하면 할 수록 늘지만, 너무 자주 하는 건 싫다. 밤늦게 할 때가 많다. 대놓고 얘기하진 않지만 남들은 어떻게 하는지 궁금하다. 교제가 거의 없다. 과정은 신경쓰지 않고, 어서 결론에 도달하려고 한다. 도구를 사용하면 도움은 되지만, 결국 사람이 해야 한다. 술을 많이 마시고 하면 다음날 어떻게 했는지 기억이 나지 않는다. 끝나고 나면 허무하고 담배가 땡긴다. 급할 때는 더 안 된다.
  • 4. 재현 진단 수정 및 반영
  • 5. 왜 재현부터? 버그가 나타날 때의 프로그램 상태를 볼 수 있다. 버그를 수정했을 때, 정말 수정했는지를 증명할 수 있다. QA팀이 재현 가능해야 한다.
  • 6. 환경 만들기 재현할 때는 문제가 되는 환경을 전부 똑같게 설정 파일, 이벤트 파일 확인, 하드웨어, OS 버전, 보안 프로그램 동작 여부 택배로 컴퓨터를 받아오기 해외에 설정 파일을 암호화해서 보내기 (3개월 전의) 해외 버전을 국내에도 유지하면 회귀 테스트 하기가 쉽다 이번 업데이트 이후 바뀐 것인지 테스트 가능
  • 7. 사례 - OpenMP 한 대의 컴퓨터에서만 에러 발생 알고 보니 특정 머신(하퍼타운4 cores)에서만 에러 발생. 이유는? 실제로 코드가 thread-safe 하지 않았음 제대로 MT 를 지원하는 머신 몰랐던 이유는? Core2 Duo 에서는 멀쩡함. 버그? 하퍼타운을 쓰는 다른 개발자는 설정에서 omp사용을 빼 놨기 때문에 에러 없었음
  • 8. 사례 보고! 현상은 원인이 있기 때문에 나타난다 정상적인 재현이 불가능하면, 억지로라도 재현한다 버그 report 를 그대로 믿지 마라 QA 에서도 아는 선에서 리포트를 쓴다 QA 분께 개인용 개발서버로 접속해서재현해 달라고 부탁한다 msn 과 사내전화 활용
  • 9. 사례 – 희귀 아이템 경매 라이브 서버가 아닌 테스트 서버, 그 중 한 npc에서만 발생 재현도안 되어서, 별 문제 없겠지 생각하고 무시 업데이트 후에 전 라이브 서버에서 문제 발생 이유 : 라이브 서버에서는 처음에 개발자가 직접 seed 값을 넣어줘서 경매에 문제 없었지만, 테스트 서버의 경우 개발자가 여러 npc중 한 npc만 까먹고 seed 값을 넣어주지 않았기 때문에 계속 문제가 있었음 처음부터 문제가 있었는데도, QA 에서는 ‘잘 되다가 저번 주부터 문제가 생겼음’ 이라고 보고했고, 개발팀도 QA 만 믿고특이한 사례보고라고 생각함 대규모 업데이트를 위해 모든 seed 값을 초기화했더니, 테스트 서버와 동일한 문제가 모든 npc에서 발생 [사례보고] 라는 제목 때문에 선입관 생김
  • 11. 사례 – 공성과 결자해지 voidLoadData(){ // do something¡¦ CCastlec(nCastleNum);// dead code??? return; }
  • 12. 사례 – 공성과 결자해지 voidLoadData(){ // do something¡¦ CCastlec(nCastleNum);// dead code? NO!!! return; } classCCastle{ public: CCastle(intn){ g_CastleDB.Register(this); } };
  • 13.
  • 14. 사례 – 기계는 믿을 수 있는가 특정 머신, CPU, 그래픽카드, NIC
  • 15. 재현 진단 수정 및 반영
  • 16. 버그 찾기 dump 로 Crash 난 위치 확인 최근에 고친 파일부터 diff 이상현상이 생긴 시간대 근처 에러로그 확인 내가 고친 코드를 먼저 의심 다른 사람과 얘기해보자 피규어 디버깅 어셈블리는 마지막에 서버라면 실제 라이브 서버를 터미널 서비스로 들어가 작업관리자로 보기
  • 17. Everybody lies false positive(거짓양성) 예전 바이너리를 쓰고 있다던가 false negative(거짓음성) QA가 고쳐지지 않은 걸 고쳐졌다고 한다 플라시보 효과 예전부터 있던 코드도 100% 믿지 말자 모든 걸 의심하자
  • 18. Dump
  • 19.
  • 20. minidump출력 Crash 이메일 전송 개발망에서도개발망email 로 전송 소스 컨트롤러에 날짜_Label 로 폴더 만든 후 바이너리, pdb를 저장 Symbol 서버 구축하기 장,단점
  • 24.
  • 25. Base Line 지금 상태는 정상인가? 평소 CPU 는 몇 % 정도였나? 의도대로 최적화가 되었나?
  • 26. Performance Counters Counter 를 log 나 DB 에 주기적으로 저장해 base line 를 만든다 counter 예시 SQL Server: SQL Statistics: Batch Requests/sec 초당 요청 받은 SQL 배치 요청 수 SQL Server: Buffer Manager: Buffer Cache Hit Ratio 90 이상이면 좋음 SQL Server: Locks: Lock Waits/sec 잠금대기요청수 Process: Page Faults/sec 프로세스가 Cache Hit하지 않은 페이지수
  • 27. 볼 수 있으면 고칠 수 있다
  • 29. Visualizer in C++ autoexp.dat으로 watch 창 변경 C:rogram Filesicrosoft Visual Studio 8ommon7ackagesebuggerutoexp.dat [AutoExpand] CMyData =head=<m_Head> m_Tail=<m_Tail,x> name=<m_Name,su> classCMyData{ public: CMyData(inth,intt): m_Head(h),m_Tail(t){} intm_Head; charm_Name[1024]; intm_Tail; }; int_tmain(intargc,_TCHAR*argv[]){ typedefvector<CMyData*>DataList; DataListdata; for(inti=0;i<10;++i){ data.push_back( newCMyData(i,i+1)); } return0; }
  • 30. Debug Windows 1 {[function],[source],[module]} 뒤에location, variable_name, expression 특정 함수의 static local 변수 보기 void Test() { static intsLocalNum = 0; } : {Test,,}sLocalNum 특정 dll의 전역변수 : {,,foobar.dll}g_pMyStruct BP 걸어놓고 함수 실행하기 classCTest{ public: staticCTest&Inst(){ staticCTests; returns; } voidCheckValidate(){ OutputDebugString(L"T"); m_Test.push_back(1); } std::vector<int>m_Test; }; int_tmain(){ CTest::Inst().CheckValidate(); return0; }
  • 31. Debug Windows 2 Pseudo Register @eax : 리턴값 @err : GetLastError @HANDLES 현재 프로세스의핸들 갯수 @ebp : 지역 변수시작 지점 @esp : 최상위 스택
  • 32. 사례 – Bot voidCPlayer::OnItemExchange( intnItemCount1,BYTE*pData1, intnItemCount2,BYTE*pData2) { for(inti=0;i<nItemCount1;++i){ // do something } for(inti=0;i<nItemCount2;++i){ // do something } }
  • 33. Fuzzing Test 임의의 입력을 만들어 주는 Fuzzer 사용 Peach Fuzzing Platform http://peachfuzzer.com/ generation 과 mutation 으로 입력값 생성 RFuzz http://rfuzz.rubyforge.org 일종의 monkey test
  • 35. Bug? (1.0<a.hP)=false (1.0>=a.hP)=false NaN(Not a Number) double answer = sqrt(-1.0);
  • 36. structCData{ static const intHALF_NUM=0x7fffffff; static const intMAX_NUM=0xffffffff; CData():m_dPoint(1.0){ m_dData[0]=1.3; m_dData[1]=1.5; m_nData[0]=HALF_NUM; m_nData[1]=MAX_NUM; } voidApplyBonus(intnBonusIndex){ m_dPoint*=m_dData[nBonusIndex]; } doublem_dPoint; doublem_dData[2]; unsignedlongm_nData[2]; }; int_tmain(intargc,_TCHAR*argv[]){ CDataa; a.ApplyBonus(2); wcout<<L"isnan : "<<_isnan(a.m_dPoint)<<L''; wcout<<L"(1.0 < a.Point) : "<<(1.0<a.m_dPoint)<<L''; wcout<<L"(1.0 >= a.Point) : "<<(1.0>=a.m_dPoint)<<L''; return0; } // output isnan:1 (1.0<a.Point):0 (1.0>=a.Point):0 -1.#R, -1.#QO, -1.#QNB, -1.#QNAN (%.2~5f 로 출력했을 때의 결과)
  • 37. 사례 – 메모리 침범 classCTest{ public: conststaticintMAX_DATA=10; intm_Data[MAX_DATA]; vector<int>m_Nums; }; int_tmain(intargc,_TCHAR*argv[]){ CTestt; t.m_Nums.push_back(1); ZeroMemory(t.m_Data,sizeof(int)*CTest::MAX_DATA+10); t.m_Nums.push_back(1);// Crash return0; } #include <boost/array.hpp> int_tmain(intargc,_TCHAR*argv[]){ intcArray[256]; boost::array<int,5>aTest={1,2,3,4 ,5}; boost::array<int,256>aArray; cArray[256]=0;// not always die aArray[256]=0;// always die // Assertion failed: i < N && "out of range", file , line 91 return0; }
  • 38. 여러 가지가 정보다 에러 로그가 찍히는 주기 CPU 가 튀는 주기 로그에 찍힌 캐릭터의 위치와 시간 이렇게 빨리 이동했다는 것은? 개발자에게 GM 용 캐릭터를!
  • 39. 사례 – 언제 문제가 발생했나? 특정 시각? 특정 요일? CPU 가 튀는 주기는? 게임 서버가 새벽 2시만 되면 죽었던 이유는? Windows Update 가 새벽 2시에 실행 바이러스 update 창이 200 개 이상 오픈 같은 port 를 bind 계속하면 port 차단 서버관리툴이 실행될 때마다 특정 port 를 bind 하게 설계 일본 IDC 에서 꼭 설치하게 하는 패킷 필터링 시스템의 DDOS, Garbage Attack 탐지기가 해당 port 를 차단 얼마만에 죽는가 특정 tick 에 죽는 잘못된 코드와 memory leak Printf대신 사용한 로그 파일이 엄청나게 커짐 Memory leak은 아니지만, 너무 많은 메모리 할당 결국 일본 찾아가서 해결
  • 40. 재현 진단 수정 및 반영
  • 43. 가와사키(Kawasaki) 이야기 Kawasaki 의 제트 스키 새로 나온 제트 스키
  • 44. 해결책에는 여러 가지가 있다(있어야 한다) 펫, 소환수 자동 소환 09.09.09 라이브 업데이트 펫인벤 아이템을 언제 주인에게 옮겨줄 것인가? 진짜 옮겨야 하나?
  • 45.
  • 46. 버그 기록 및 공유 버그 트래킹 툴에 FIX 할 때, 실제로 어떤 코드를 왜, 어떻게 고쳤는지 정보를 남긴다 누구보다 내가 나중에 그 정보를 필요로 하게 된다 일일회의 할 때 실수를 용기있게 공유한다 고참 개발자일수록 먼저 일일회의 내용을 각자 위키에 써 놓으면, 코드 변경 히스토리에서 버그를 만든 날짜에 내가 뭘 하려고 했는지를 알 수 있다 해결한 문제에 대해, 원인-해결책을 시간, 문제별로 정리해 놓으면, 몇 달 후 해외에서 같은 문제가 생겼을 때 빨리 해결할 수 있다.
  • 47. 좋은 코드 작성하기 voidTest1(CTest*p){ // do something } voidTest2(CTest&t){ // do something }
  • 48. voidTest1(CTest*p){ if(p){ Test1_1(p); }else{ // do something } } voidTest1_1(CTest*p){ if(p){ // do something } } voidTest2(CTest&t){ Test2_1(t); } voidTest2_1(CTest&t){ // do something }
  • 49. Source: Coverity White Paper
  • 50. 버그의 비용 Source: Coverity White Paper
  • 51. 버그 미리 찾기 _ASSERT !! Magic bit 사용 int 를 int64 로 바꾸면서 magic bit 끼워넣기 특정 bit 가 1 이 아니면 crash 정기적인 코드 리뷰 코드리뷰 별 거 아님 정적 분석툴과 CI 연동 일일빌드(TeamCity, CruiseControl.Net) Code Analysis pc-lint PMD Copy/Paste Detector
  • 52.
  • 53. 포인터에 대한 사용 주의 경고, 중복된 변수 선언
  • 54. 묵시적 Type Casting, sprintf 의 인자 개수 체크
  • 55. 단 x64 는지원하지 않으므로 편법을 좀 써야 함longlData[10]; sValue.Format("%d",lData[10]); warningC6201:Index'10'isoutofvalidindexrange'0'to'9'forpossiblystackallocatedbuffer'lData¡¯ voidCTest::DrawData(CDC*pDC){ ASSERT(pDC); pDC->FillSolidRect(rect,RGB(255,0,0)); } CRectrcTmp; for(...){ CRectrcTmp; }
  • 57.
  • 59.
  • 60. 단위 테스트 적용 사례 사례 - 활 쏘기 활은 레이저 빔이 아니다 활은 포물선을 그리며 날아간다 그럼 이런 경우는?
  • 61.
  • 62.
  • 63.
  • 64.
  • 65. 해결방법 structTestBowData { Pos from; Pos to; bool expect; }; TestBowData data[] = { { {10, 20, 10}, {100, 40, 50}, true}, // 성공해야 함 { {334, 13, 314}, {525, 11, 42}, false}, // 실패해야 함 …. }; for (inti = 0; i < dataSize; ++i) { TestBowData& d = data[i]; _ASSERT(d.expect == TestCanShoot(d.from, d.to)); }
  • 67. 간단한 Mock 만들기 classCTest{ protected: intm_Test; voidTest(){} }; structCMockTest:publicCTest{ public: usingCTest::m_Test;// 부모 클래스의 멤버를 public 으로 쓰겠다. usingCTest::Test; }; int_tmain(intargc,_TCHAR*argv[]){ CTesta; //a.m_Test = 1; // protected 멤버 변수 접근할 수 없음. //a.Test(); // protected 멤버 함수 접근할 수 없음. CMockTest*pMockTest=(CMockTest*)(&a); pMockTest->m_Test=1;// CMockTest로 강제 캐스팅하면 접근할 수 있음. pMockTest->Test(); // a 가 CMockTest객체가 아니어도 이렇게 쓸 수 있다는 점에 주의 return0; }
  • 68. Memory Leak Detector #define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1)) #define pHdr(pbData) (((_CrtMemBlockHeader *)pbData)-1) FILE*g_hfileLog=NULL; intAllocHook(intnAllocType,void*pvData,size_tnSize,intnBlockUse, longlRequest,constunsignedchar*szFileName,intnLine){ staticsize_tsizeAlloc=0; _CrtMemBlockHeader*pHead; if(nBlockUse==_CRT_BLOCK)// alloced by c lib returntrue; switch(nAllocType){ case_HOOK_ALLOC: sizeAlloc+=nSize; fprintf(g_hfileLog,"ALLOC%d",sizeAlloc); break; case_HOOK_REALLOC: break; case_HOOK_FREE: pHead=pHdr(pvData); sizeAlloc-=pHead->nDataSize; fprintf(g_hfileLog,"FREE%d",sizeAlloc); break; } returntrue; } int_tmain(intargc,_TCHAR*argv[]){ g_hfileLog=fopen("log.txt","w+"); fprintf(g_hfileLog,"Start"); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); _CrtSetAllocHook(AllocHook); fclose(g_hfileLog); return0; } #include <crtdbg.h> #define nNoMansLandSize 4 typedefstruct_CrtMemBlockHeader{ struct_CrtMemBlockHeader*pBlockHeaderNext; struct_CrtMemBlockHeader*pBlockHeaderPrev; char*szFileName; intnLine; #ifdef _WIN64 /* These items are reversed on Win64 to eliminate gaps * in the struct and ensure that sizeof(struct)%16 == 0, * so 16-byte alignment is maintained in the debug heap. */ intnBlockUse; size_tnDataSize; #else /* _WIN64 */ size_tnDataSize; intnBlockUse; #endif/* _WIN64 */ longlRequest; unsignedchargap[nNoMansLandSize]; // followed by: // unsigned char data[nDataSize]; // unsigned char anotherGap[nNoMansLandSize]; }_CrtMemBlockHeader;
  • 69. Memory Leak Detector Memory Pool 대신 new, delete 를 쓰게 만드는 flag 를 하나 둘 것 이러면 LeakDiag, gflags, UMDH 로 버그 찾기도 훨씬 쉽다
  • 71.
  • 73. 결론 버그 찾는 법을 수련하자 어떻게든 재현하자 작은 버그도 무시하지 말자 쓰고 있는 툴을 최대한 활용하자 해결책을 최소 2 개 이상 생각해보자 버그를 미리 막을 방법을 만들어보자 단위테스트를 활용하자 서로의 경험을 공유하자
  • 74. Q/A
  • 76. 버그 정의 디버깅 .NET 응용 프로그램 가와사키 애자일의 미래(http://agile.egloos.com/3182427) 미니 덤프 http://hhko.egloos.com/891853 크래시 덤프 분석기 http://blog.maiet.net/xe/4596 성능 카운터 http://serious-code.net/moin.cgi/WindowsPerformanceMonitoring Visualizer http://minjang.egloos.com/468834 Stack 깨졌다면 실전 윈도우 디버깅 5장 p.235 NaN(Not a Number) http://msdn.microsoft.com/en-us/library/w22adx1s%28VS.80%29.aspx
  • 77. 편작 이야기 http://www.m-letter.or.kr http://blog.daum.net/suknyangdari/1810 Code Analysis http://eslife.tistory.com/entry/Visual-Studio-2005%EC%9D%98-Code-Analysis-%EA%B8%B0%EB%8A%A5 http://whiteapple.textcube.com/224 펫, 소환수 자동 소환 http://www.playforum.net/lineage2/board.comm?action=read&iid=10032291&pageNo=0&num=16102 http://www.playforum.net/lineage2/board.comm?action=read&iid=10032298&pageNo=0&num=14443 Memory Leak Detector http://cozyhouse.tistory.com/entry/Win32%EC%97%90%EC%84%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%82%AC%EC%9A%A9%EB%9F%89-%EC%B8%A1%EC%A0%95%EB%B0%A9%EB%B2%95 버그 종류 http://mschnlnine.vo.llnwd.net/d1/pdc08/PPTX/PRECONF/PRE02.pptx
  • 78. 사진 출처 the Copulation http://www.bmj.com/cgi/content/full/319/7225/1596 http://wuli.com/?p=1991 측우기 http://www.pureunschool.org/bbs/board.php?bo_table=dmake&wr_id=7 필승교 http://tvpot.daum.net/clip/ClipView.do?clipid=18199953%26q=%EB%8C%80%ED%94%BC%EC%8B%9C%EA%B0%84%26searchType=0%26sort=wtime%26svctype=1%26focus=1 매듭 http://www.opentory.com/index.php/%EB%A7%A4%EB%93%AD 심볼 서버 http://www.codeguru.com/cpp/v-s/debug/debuggers/article.php/c15355__2/ 그래픽 카드 테스트실 http://chulin28ho.egloos.com/5044251