85.21 assert 사용하기

assert 매크로는 assert.h 헤더 파일에 정의되어 있으며 정해진 조건에 맞지 않을 때 프로그램을 중단합니다. 즉, assert에 지정한 조건식이 거짓(false)일 때 프로그램을 중단하며 참(true)일 때는 프로그램이 계속 실행합니다.

  • assert(표현식)

단, NDEBUG 매크로가 정의되어 있으면 assert는 무시됩니다. 그러므로 Visual Studio에서는 Debug 모드에서만 동작하며 Release 모드에서는 동작하지 않습니다.

예를 들어 포인터가 NULL이면 프로그램을 중단하도록 만들어보겠습니다.

assert.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <assert.h>     // assert가 정의된 헤더 파일

void copy(char *dest, char *src)
{
    assert(dest != NULL);    // dest이 NULL이면 프로그램 중단
    assert(src != NULL);     // src가 NULL이면 프로그램 중단

    strcpy(dest, src);       // 문자열 복사
} 

int main()
{
    char s1[100];
    char *s2 = "Hello, world!";

    copy(s1, s2);     // 정상 동작

    copy(NULL, s2);   // NULL이 들어갔으므로 프로그램 중단
    // Assertion failed: dest != NULL, file c:\project\assert\assert\assert.c, line 8
    
    return 0;
}

실행 결과(Visual Studio)

Assertion failed: dest != NULL, file c:\project\assert\assert\assert.c, line 8

실행 결과(GCC)

assert: assert.c:8: copy: Assertion `dest != ((void *)0)' failed.

소스를 컴파일하여 실행해보면 프로그램을 중단시킨 assert의 정보가 표시됩니다(함수 이름, 조건식, 파일명, 줄 번호 등).

copy 함수를 보면 assert(dest != NULL);와 같이 포인터 destNULL이 아니면(참) 프로그램을 계속 실행하도록 만들어져 있습니다. 반대로 이야기하면 destNULL이면(거짓) 프로그램을 중단합니다.

void copy(char *dest, char *src)
{
    assert(dest != NULL);    // dest이 NULL이면 프로그램 중단
    assert(src != NULL);     // src가 NULL이면 프로그램 중단

    strcpy(dest, src);       // 문자열 복사
}

아무래도 assert는 조건식과 동작 방식이 좀 헷갈립니다. 그래서 assert의 조건식을 지정할 때는 항상 올바른 상황을 정한다고 생각하면 쉽습니다. 여기서는 strcpyNULL이 들어가면 안 되므로 assert(dest != NULL);assert(src != NULL);이 항상 올바른 상황입니다.

이제 copy 함수 호출 부분을 보면 copy(s1, s2);와 같이 문자 배열과 문자열 포인터가 들어가는 상황은 올바른 상황입니다. 하지만 copy(NULL, s2);와 같이 NULL이 들어가면 함수 안의 assert는 거짓이 되므로 프로그램이 중단됩니다.

char s1[100];
char *s2 = "Hello, world!";

copy(s1, s2);     // 정상 동작

copy(NULL, s2);   // NULL이 들어갔으므로 프로그램 중단
// Assertion failed: dest != NULL, file c:\project\assert\assert\assert.c, line 8

사실 assert 없이 strcpy 함수에 바로 NULL이 들어가도 에러가 발생하고 프로그램은 중단됩니다. 하지만 strcpy 함수에서 에러가 나는 상황은 여러 가지이므로 버그를 찾으려면 모든 상황을 조사해야 됩니다. 이때 미리 assert로 일어나서는 안되는 상황을 정의해놓으면 버그를 빠르게 찾을 수 있습니다.

C 언어를 배울 때는 assert를 사용할 일이 거의 없지만 실무에서는 함수마다 assert를 자주 사용합니다. 나중에 assert를 만나게 되면 이 부분을 찾아보세요.