· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
xassert

아직 완전하지 않은 내용입니다. 수정하기 전에 CCodeSnippets를 읽어 주시기 바랍니다. -- cinsk

Interface

Synopsis

#include <xassert.h>

void xassert(scalar expression, const char *format, ...);

Description

만약 <xassert.h>를 포함할 때, NDEBUG 매크로가 정의되어 있으면 xassert()는 아무런 일을 하지 않으며, NDEBUG가 정의되어 있지 않으면, printf(3) 스타일의 메시지를 출력할 수 있다는 것을 제외하고, assert(3)와 똑같이 동작한다.

Note

ISO C를 지원하는 시스템에서 쓸 수 있다. 정확히 말하면, 매크로 VA_ARGS를 지원하는 컴파일러에서 쓸 수 있다.

Introduction


assert(3)는 개발자가 프로그램을 작성할 때, 버그가 생기는 것을 막아주는 가장 기초적인 방법 중의 하나입니다. TODO: assert()에 대해서 좀 더 설명

assert(3)의 출력은 정해지지 않아서, 컴파일러마다 조금씩 다릅니다만1, 대개의 경우, assert가 발생된 소스의 파일 이름과 줄 번호를 알려주면서 프로그램을 강제로 끝냅니다. 끝낼 때에는 abort(3)를 사용하도록 되어 있습니다.

예를 들어 아래의 출력은 어떤 시스템의 assert(3) 출력 결과입니다.
$ cat tmp.c
#include <assert.h>

void
adult_only(int age)
{
  assert(age > 18);
}

int
main(void)
{
  adult_only(3);
  return 0;
}
$ gcc tmp.c
$ ./a.out
a.out: tmp.c:6: adult_only: Assertion `age > 18' failed.
Aborted
$ _
assert()를 효과적으로 수행하기 위해서, 개발자가 직접 메시지를 써 넣을 수 있으면 참 편할 것이라 생각합니다. 즉 단순히 어떤 수식(위에서는 "age > 18")을 출력하고 종료하기 보다는, printf()와 같은 형식의 메시지도 함께 출력할 수 있다면 나중에 assert()가 발생할 때, 왜 발생했는지 이유를 빠르게 알아낼 수 있을 것입니다. 결국 우리가 만들고자 하는 것은 다음과 같은 코드를 만들 수 있게 하고:
xassert(age > 18, "AGE must be 19 at least. (age = %d)", age);
실제로 조건을 만족하지 않을 경우, 다음과 같은 메시지를 출력하게 하려는 것입니다:
a.out: tmp.c:6: adult_only: Assertion `age > 18' failed.
        AGE must be 19 at least. (age = 3)

Implementation

assert(3)는 매크로 NDEBUG가 정의되어 있는 경우, ((void)0)으로 확장되어 실제로 기계어 코드를 만들어내지 않습니다. 따라서 최대한 오버헤드를 적게 하기 위해서는 ASSERT도 다음과 같이 매크로 함수로 정의되어야 합니다.
#ifndef NDEBUG
# define xassert(x, ...)        /* 메시지 출력하고 종료.. */
#else
# define xassert(x, ...)        ((void)0)
#endif

가변 인자를 처리하는 매크로에 대해서는 CLanguageVariableArgumentsList에서 설명했습니다. 기억이 잘 나지 않는다면 다시 읽어보시기 바랍니다. 이제 위 코드에서 주석 부분을 써 넣어야 하는데, 다음과 같은 함수를 만들어서 대체하려고 합니다.
void
assert_(const char *filename, int lineno, const char *funcname,
        const char *expr, const char *format, ...)
{
  va_list ap;
  fflush(stdout);
  fprintf(stderr, "%s:%d: Assertion `%s' failed.\n",
          filename, lineno, expr);
  va_start(ap, format);
  vfprintf(stderr, format, ap);
  va_end(ap);
  fputc('\n', stderr);
  abort();
}
가변 인자를 처리하는 함수에 대해서 기억이 나지 않는다면, CLanguageVariableArgumentsList를 참고하기 바랍니다. 이제 xassert의 정의를 다음과 같이 다시 쓸 수 있습니다 (NDEBUG 관련 부분은 제외합니다):
void assert_(const char *filename, int lineno,
             const char *funcname,
             const char *expr, const char *format, ...);
#define xassert(x, ...) do {                                      \
                            if (!(x))                               \
                              assert_(__FILE__, __LINE__, __func__, \
                                      #x, __VA_ARGS__);             \
                        } while (0)

TODO: 몇가지 사용례 추가



Sources

xassert.h

/* $Id: xassert,v 1.12 2005/03/22 06:56:28 kss Exp kss $ */
/*
 * Enhanced assert(3)
 * Copyright (C) 2003, 2004  Seong-Kook Shin <cinsk.shin at samsung.com>
 */
                                                                                
#ifndef XASSERT_H_
#define XASSERT_H_
                                                                                
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
                                                                                
/* This indirect writing of extern "C" { ... } makes Emacs happy */
#ifndef BEGIN_C_DECLS
# ifdef __cplusplus
#  define BEGIN_C_DECLS  extern "C" {
#  define END_C_DECLS    }
# else
#  define BEGIN_C_DECLS
#  define END_C_DECLS
# endif
#endif /* BEGIN_C_DECLS */
                                                                                
BEGIN_C_DECLS
                                                                                
#ifndef NDEBUG
extern void assert_(const char *file, long line, const char *func,
                    const char *expr, const char *format, ...);
# define xassert(condition, ...)  do {                                        \
                                    if (!(condition))                         \
                                      assert_(__FILE__, __LINE__, __func__,   \
                                              #condition, __VA_ARGS__);       \
                                  } while (0)
                                                                                            
#else
# define xassert(condition, ...)  ((void)0)
#endif /* NDEBUG */
                                                                                            
                                                                                          
END_C_DECLS
                                                                                            
#endif /* XASSERT_H_ */

xassert.c

/* $Id: xassert,v 1.12 2005/03/22 06:56:28 kss Exp kss $ */
                                                                                            
/*
 * Enhanced assert(3)
 * Copyright (C) 2003, 2004  Seong-Kook Shin <cinsk.shin at samsung.com>
 */
                                                                                            
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
                                                                                            
#include <xassert.h>
                                                                                            
                                                                                            
void
assert_(const char *file, long line, const char *func,
        const char *expr, const char *format, ...)
{
  va_list ap;
                                                                                            
  fflush(stdout);
  fflush(stderr);               /* possibly redundant */
  fprintf(stderr, "%s:%ld: Assertion `%s' failed at %s.\n\t",
          file, line, expr, func);
  va_start(ap, format);
  vfprintf(stderr, format, ap);
  va_end(ap);
  fputc('\n', stderr);
  fflush(stderr);               /* possibly redundant */
  abort();
}
                                                                                            
                                                                                            
#ifdef TEST_XASSERT
int
main(void)
{
  int age = 1;
  ASSERT(age > 10, "Age should be larger than 10. (age = %d)", age);
  return 0;
}
#endif /* TEST_XASSERT */


ID
Password
Join
The wise shepherd never trusts his flock to a smiling wolf.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2005-03-22 15:56:28
Processing time 0.0072 sec