Seize the day

POST : SDP for win32/디버깅

ASSERT, TRACE, LOGGING

ASSERT


ASSERT( and VERIFY)와 TRACE는 디버깅의 가장 기본적인 방법이다. ASSERT는 반드시 TRUE여야함을 체크하고 실패한 경우 Assert 실패창을 노출해 준다.  TRACE는 Dbgview.exe에 문자열을 출력한다. 


모듈의 테스트는 유닛테스트를 이용하는 것이 정석이지만, UI 코드의 테스트는 유닛테스트로 만들기가 까다롭다.  ASSERT와 TRACE는 개발자가 프로그램을 실행하는 중에  UI 테스트를 자동으로 해 준다는 점에서 매력적이다.  이 두  매크로는 정말 좋지만 몇 가지 단 점이 있다. 

- DEBUG 모드에서만 쓸 수 있다. 

- ASSERT 실패시에 변수 값을 확인하기 어렵다.


class __test

{

public:

int getAt(int index)

{

ASSERT(index >=0 && index < _countof(m_a) );

    _ASSERT_EXPR(index >=0 && index < _countof(m_a), __S(L"index = %d", index) );

return m_a[index];

}

private:

int m_a[5];

};


void Test5()

{

__test t;

int a = t.getAt(5);

UNREFERENCED_PARAMETER(a);

}


결과는 아래와 같다. 


_ASSERT_EXPR를 이용하면  변수 값도 확인이 가능하기는 하다. 

두 매크로 모두 검사한 코드인  (index >=0 && index < _countof(m_a)는 확인이 안 된다. (참고로  ATLASSERT 는 확인이 가능하다.)



개선된 어썰트 매크로는 DCHECK 이며 사용법은 아래와 같다.

DCHECK(index >=0 && index < _countof(m_a) ) << "index = " << index;


결과는



바뀐 점은 함수명이 나오고,  테스트한 코드도 노출되며, 변수 값도 확인이 가능하다. 콜스택도 노출이 된다. 




만약 릴리스 모드에서 ASSERT를 노출하고 싶다면


#define  USE_LOGGING_RELEASE_ASSERT

#include <logging.h>

logging.h을 include 하기 전에 define 값 하나 추가 하면 된다.




릴리스 모드 어썰트는 어떤 경우에 유용할까. 프로그램을 최종 사용자에게 배포되기 전에 많은 유관 부서에 먼저 공유가 된다.  보통 개발자 테스트 단계 => FGT (Focus Group Test) 단계(개발, UX, 디자인, 그 외 협업 팀) ==> Q/A 단계 ==> 사내 베타 ==> 릴리스 단계가 있는데 테스트 빌드가 공유가 되면 뭐가 안 된다며 개발확인을 요청하는 경우가 많다. 이런 경우 릴리스 모드 어썰트가 도입이 되면 오류 확인이 즉각적으로 가능해 진다. 


  내 생각에 Q/A 테스트가 1차, 2차 등 여러 차 수가 있다면 Q/A 1차 까지는 릴리스모드 어썰트가 포함되어 배포되어도 문제가 없다고 본다. 모든 코드에서 릴리스 모드 어썰트를 빼는 것은 단 1줄만 주석처리하면 되기 때문에, 릴리스 모드 어썰트가 출시되는 경우는 걱정하지 않아도 된다. 실제로 UltraMon 이라는 프로그램에서 릴리스 모드 어썰트창이 뜨는 것을 보았다 비록 소스 파일명과 라인수만 노출되기는 했지만 ...


CheckReturnValue 라는 매크로는 실패시 어썰트창을 띄우고, Value (두 번째 인자)를 리턴하도록 구현되어 있다. 어썰트 실패창이 뜰 때 변수값도 노출이 가능하다. 

int getAt(int index)

{

CheckReturnValue(index >=0 && index < _countof(m_a), -1, <<"index=" <<index );


return m_a[index];

}


logging.h의 매크로를 정할 때 한 가지 규칙이 있는데 모두 대문자인 매크로는  디버깅모드에서만 동작한다. 

DCHECK의 실제 구현은 NCheck 매크로를 이용한다.  NCheck는 릴리스모드 어썰트창을 띄우는 실제 구현 매크로다. 



TRACE

트레이슨 두 가지 매크로만 있다. 

DTRACE() << "something ...";

NTrace() << "release mode tracing...";


DTRACE는 디버그모드에서만 동작한다.  NTrace는 릴리스 모드에서도 동작한다. 




LOGGING

2 가지 초기화

LogInitialize(L"logging", L"exe", 0, true, true);

LogInitializeFromReg(L"logging", L"exe", L"software\\logging");

/*

[HKEY_LOCAL_MACHINE\SOFTWARE\logging]

"logTrace"=dword:00000001

"logLevel"=dword:00000000

"logFile"=dword:00000001

*/

logLevel은 0에서 5까지 지정이 가능하다. 높을수록 크리티컬한 로그만 남는다.



파일 혹은 TRACE로 로그를 남길 수 있다. 로그는 레벨이 있으며 레벨을 지정하면 로그를 필터링 할 수 있다. 

NLog() << "nlog";

NLogDebug() << "nlog debug";

NLogInfo() << "nlog info";

NLogWarning() << "nlog warning";

NLogError() << "nlog error";

NCheck(false) << "ncheck failed..";

NVerify(false) << "nverify failed..";

DLOG() << "dlog";

CheckReturnValue(index >=0 && index < _countof(m_a), -1, <<"check failed index=" <<index );


출력결과는 아래와 같다. 

[192] [logging-exe-LOG](00:55:15) file:.\Test.cpp line:252 function:__test::getAt :nlog

[192] [logging-exe-DEBUG](00:55:15) file:.\Test.cpp line:253 function:__test::getAt :nlog debug

[192] [logging-exe-INFO](00:55:15) file:.\Test.cpp line:254 function:__test::getAt :nlog info

[192] [logging-exe-WARNING](00:55:15) file:.\Test.cpp line:255 function:__test::getAt :nlog warning

[192] [logging-exe-ERROR](00:55:15) file:.\Test.cpp line:256 function:__test::getAt :nlog error

[192] [logging-exe-ASSERT](00:55:15) file: .\Test.cpp

[192] line: 257

[192] function: __test::getAt

[192] expr: false

[192] 

[192] ncheck failed..

[192] [logging-exe-ASSERT](00:55:16) file:.\Test.cpp line:258 function:__test::getAt :expr: false :nverify failed..

[192] [logging-exe-ASSERT](00:55:16) file:.\Test.cpp line:259 function:__test::getAt :expr: index >=0 && index < _countof(m_a) :check failed index=5



Dbgview.exe에서 "-ASSERT]" 문자열로 컬러링을 지정해 두면 중요 로그는 확인이 쉬어진다.

DLOG는 디버그 모드에서만 동작한다.


릴리스 모드에서 NCheck, NVerify, CheckReturnValue 는 로그가 켜져 있는 경우 자동적으로 로그를 남기도록 구현했다. 따라서 매크로 하나로 어썰트 실패시 디버그 모드에서는 어설트창으로 릴리스 모드에서는 로그파일로 에러를 확인할 수 있는 이점이 있다.


모든 소스코드는 

http://dev.naver.com/projects/sdp

에서 내려 받을 수 있다. (src\base\logging.h logging.cpp 참조 )












top

posted at

2013. 8. 28. 01:11


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크