C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 자료실
C++Builder Programming Resources
[310] 디버깅을 위한 빌더용 사용자 ASSERT (수정1)
김태선 [jsdkts] 16266 읽음    2006-05-20 01:57
// 수정1.
// ASSERT 매크로가 조건검사를 하지 않아 수정합니다. 이런 실수를 -ㅡㅡ; 지송...
// 또 기존 assert를 ASSERT 로 변경하는 매크로도 추가합니다.
// 소스가 있으니 입맛에 맞게 변경해 사용하셔도 됩니다.
//---------------------------------------------------------------------------

빌더에는 디버깅을 위해 필요한 조건을 충족하지 못할 경우
그 조건의 내용을 화면에 표시한 뒤
중간에 프로그램을 강제로 종료하는 assert 매크로가 준비되어 있습니다.
VC++에서는 ASSERT 를 사용하는데 비해 빌더는
#include <assert.h>를 한 뒤
assert(조건);
식으로 사용합니다.
assert는 조건이 참인 경우는 그대로 다음 줄로 진행하고 참이 아닌 경우는 그 조건식을 화면에 표시하면서
프로그램이 중단된다는 것은 다 아시죠, ^^;;

그런데, 프로그램하다보면 assert가 별로 마음에 들지 않을때가 있습니다.
사용자 맘에 드는 assert를 구성하고 싶을 때가 있을 수 있으며,
아무리 디버깅 도중 조건테스트에서 중간에 프로그램을 종료한다 하더라도
무언가 불시 종료전에 해주고 싶은 동작이 있을 수 있습니다.

그래서 사용자용 ASSERT를 만들어 올립니다.
소스를 플젝에 포함한뒤
ASSERT(조건);
식으로 사용하면 됩니다.
아래 스샷은 예입니다.


필요하다면 중단 소스를 바꿀 수 도 있습니다.
아마 assert의 동작보다  보기 좋고 중간에 중단되는 것에 대해
사용자 코드를 부가할 수 있으므로 덜 불안할 것입니다.

릴리즈모드에서나 ASSERT_OFF 를 선언한다면
ASSERT 관련 코드는 바이너리 이진코드에서는 완전히 제거됩니다.
이렇게 된다면 ASSERT 동작이 사라지므로 프로그램의 에러를 완전히 잡고난 뒤 릴리즈해야 겠죠.
물론 ASSERT 코드를 포함해서 릴리즈해도 무방합니다.
사용자가 에러난 경우 에러메시지를 쉽게 통보할 수 있어 에러를 쉽게 파악할 수 있으므로,
상용 프로그램에 ASSERT 코드를 그대로 두고 릴리즈하는 경우도 있습니다.

아뭏던 소스가 있으니 적당히 고쳐서 사용할 수 있다는데 큰 의미가 있습니다.

소스를 첨부했지만 간단하므로 여기에 한번 더 나열하겠습니다.

ASSERT.h
//---------------------------------------------------------------------------
// 사용자 ASSERT
// Written by 김태성 jsdkts@korea.com
//---------------------------------------------------------------------------

#ifndef ASSERTH
#define ASSERTH

#define xASSERT_OFF
#if (defined(ASSERT_OFF) || !defined(_DEBUG))

// 릴리즈모드에서는 ASSERT을 모두 제거하기 위함이다.

#define ASEERT 1 ? (void) 0 : ___DeleteASSERT
inline void ___DeleteASSERT(const char *str, ...)
{
    // empty code.
}

#else

#define ASSERT(p)     if (!(p)) ASSERT_FUNC(#p, __FILE__, __FUNC__, __LINE__)
void    ASSERT_FUNC(char *condition, char *file, char *func, int line);

/*
// 헤더 하나로만 사용하고 싶은 경우 inline으로 선언된 아래 함수를 사용하면 됩니다.
inline void    ASSERT_FUNC(char *condition, char *file, char *func, int line)
{
    char     szBuffer[4097];

    wsprintf(szBuffer, "%s\n\n소스파일: %s  라인 %d\n함수명 : %s\n",
        condition, file, line, func);
    MessageBox(NULL, szBuffer, "ASSERT", MB_OK | MB_ICONWARNING);
    Application->Terminate();
    throw Exception("ASSERT 종료: Application terminate");
}
*/

#endif


#endif


ASSERT.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ASSERT.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

static void    ASSERT_FUNC(char *condition, char *file, char *func, int line)
{
    char     szBuffer[4097];

    wsprintf(szBuffer, "%s\n\n소스파일: %s  라인 %d\n함수명 : %s\n",
        condition, file, line, func);
    MessageBox(NULL, szBuffer, "ASSERT", MB_OK | MB_ICONWARNING);

    // 이런식의 종료를 해도 좋고, 사용자가 코드를 추가하거나 바꾸어도 좋습니다.
    Application->Terminate();
    throw Exception("ASSERT 종료: Application terminate");
}


사용은
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int  k = 1;
    ASSERT(k == 2); // 여기 ASSERT 조건
    int     kk = k;
    Caption = kk;
    MessageBox(NULL, "test", "ttt", MB_OK);
}
식으로 한다면 ASSERT 구문의 조건이 false가 되므로
해당 줄의 조건과 소스파일명, 함수명, 라인번호를 표시한뒤 프로그램은 중단되게 됩니다.
즉 위에서 ASSERT 다음 줄은 전혀 실행이 안되게 되죠.
ASSERT_FUNC 함수 소스에서 중단코드를 살펴보면 메시지를 표시한뒤
어플 종료 함수를 부르고 난 뒤 예외를 발생시켜 순리적으로 종료시킵니다.
화면 모습은 아래와 같습니다.


그럼.

+ -

관련 글 리스트
310 디버깅을 위한 빌더용 사용자 ASSERT (수정1) 김태선 16266 2006/05/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.