프로그램을 만들다보면 이런저런 예외처리나 에러가 날법한 곳에 메세지박스나 콘솔창에 디버그 결과를 띄울경우가 많다. 그러다 assert 매크로를 알게 되었는데, 너무나도 유용하면서 편하게 디버깅을 할수 있는 방법이다. 직접 블로깅 하려다가, 어떤 분께서 아주 정리를 깔끔하게 해놓으셔서 긁어오게 되었다. 출처 및 주소는 밑에..
" assert의 비법들 "
1. assert의 기본
- assert 매크로 : 코드 상의 어떠한 가정을 철저하게 점검하기 위한 간단하면서도 부담 없는 방법
- 항상 TRUE가 되어야 하는 조건식을 넣는다. 조건이 FALSE로 평가되면 assert는 문제가 생겼음을 알리는 대화상자를 띄운다.
- 프로그램을 방어적으로 만들어 준다.
- 디버그 빌드에서는 수행하지만 릴리즈 빌드에서는 assert 매크로가 컴파일되지 않는다. 그러므로 assert 안에서 프로그램의 상태를 변화시켜서는 안된다.
#include <assert.h>
void VectorNormalize( Vec* src, Vec* dst ) {
assert( src != 0 );
assert( dst != 0 );
}
2. assert 비법_1) 더 많은 정보를 집어넣는다.
- assert의 조건식에 더 많은 정보를 집어 넣는다.
#include <assert.h>
void VectorNormalize( Vec* src, Vec* dst ) {
assert( src != 0 && "VectorNormalize::src vector pointer is NULL " );
assert( dst != 0 && "VectorNormalize::dst vector pointer is NULL " );
}
3. assert 비법_2) 좀더 많은 정보를 집어넣는다.
- 프로그램의 실행이 도달하지 말아야 할 곳에 도달하는 상황을 감지하기 위해서 assert(0)를 사용하는 경우도 있다. 항상 실패.
- 부정 연산자 사용
- assert( !"VectorNormalize:: The code should never get here" );
4. assert 비법_3) 좀더 편하게
- 두 개의 인자들을 받는데, 첫번째 것은 실제로 평가될 조건식이고 두번째 것은 디버깅 정보를 담는 문자열이다.
- #define Assert(a,b) assert( a && b )
- Assert( src != 0, "VectorNormalize::src vector pointer is NULL " );
Assert( 0, "VectorNormalize:: The code should never get here" );
5. assert 비법_4) 커스텀 assert 만들기
- assert보다 더 많은 기능을 가진 독자적인 검사 매크로를 만들 수 있다.
- 디버거 하에서 조건이 실패ㅏㄹ 경우 소스파일 안의 assert 문이 아니라 assert.c 파일 안에서의 assert 문으로 들어가게 되는 경우 소스파일로 직접 들어가게 만들때 사용된다.
#if defined(_DEBUG)
extern bool CustomAssertFunction( bool, char*, int, char* );
#define Assert( exp, description ) \
if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \
{ _asm { int 3 } }
#else
#define Assert( exp, description )
#endif
6. assert 비법_5) 이것도 중요
- 커스텀 assert 매크로를 만드는 경우에는 assert 대화상자에 다음부터 항상 무시 옵션을 추가하는 것이 좋다
- 특정 assert 문에 대해서는 조건이 실패해도 대화상자를 표시하지 않고 무조건 넘어갈 수 있도록 하는 것이다.
#if defined(_DEBUG)
extern bool CustomAssertFunction( bool, char*, int, char* );
#define Assert( exp, description ) \
{ static bool ignoreAlways = false; \
if( !ignoreAlways ) { \
if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \
{ _asm { int 3 } }
} \
}
#else
#define Assert( exp, description )
#endif
7. assert 비법_6) 초고수만 볼 것
- VectorNormalize를 호출하는 곳이 많다면 VectorNormalize 안의 assert 문은 프로그램을 디버거에 붙여서 실행하지 않는 한 큰 도움이 되지 못한다.
- assert 대화상자 안에 스택 정보를 표시하면 된다.
8. assert 비법_7) 좀 더 쉽게 복사해서 붙여 넣기
- 스택 정보를 좀 더 쉽게 보존/저장할 수 있는 방법이 필요
- 윈도우즈 환경에서의 한 가지 해결책은 클립보드를 이용하는 것
- assert 대화상자에 작은 버튼을 하나 만든 다음 그 버튼을 클릭할 때 스택 정보가 클립보드에 복사되도록 하면 누구라도 쉽게 클립보드의 내용을 버그 리포트나 전자 우편에 붙여 넣어서 프로그래머에게 보낼 수 있다.
- 임의의 문자열을 클립보드에 복사하는 윈도우즈 전용 코드
if( OpenClipboard( NULL ) )
{
HGLOBAL hMem;
char szAssert[256];
char *pMem;
sprintf( szAssert, "Put assert info here" );
hMem = GloabalAlloc( GHND | GMEM_DDESHARE, strlen( szAssert ) + 1 );
if( hMem)
{
pMem = (char*)GlobalLock(hMem);
strcpy( pMem, szAssert );
GlobalUnLock( hMem );
EmptyClipboard();
SetClipboardData( CF_TEXT, hMem );
}
CloseClipboard();
}