본문 바로가기
이론/[책]WRITINGSOLIDCODE

[2장]ASSERT YOURSELF

by 사과잼빵 2017. 2. 12.

strCopy = memcpy(malloc(length), str, length);

위와 같은 코드에서 새로운 메모리릉 할당하는 malloc 함수가 실패한다면 memcpy 함수에 NULL포인터를 전달하게 되면서 memcpy는 정상적인 작동이 불가능하다.
따라서 예외 처리를 한다면 memcpy함수에 아래와 같이 예외처리를 추가 해 줄 수 있다.

void memcpy(void* dst, void* src, size_t size)
{
    if( dest == NULL || src == NULL)
    {
        // 에러 발생
    }
   
    //~~ 복사 처리 //

}

위와 같이 코드를 작성하면 NULL포인터 문제를 막을 수 있다. 하지만 코드량이 늘어나고 수행해야할 코드가 늘면서 속도가 저하게되게 된다.
따라서 상업용 프로그램을 개발할 때는 두가지 버전으로 코드를 관리해아할 필요가 있다.
하나는 깔끔하고 빠른 출시용 버전이고 또 하나는 속도가 느리고 각종 검사 코드가 들어가 있는 버전이다.
선행 처리기 덕분에 별도의 파일로 관리할 필요 없이 코드를 분리 시킬 수 있다.
예를 들면 위의 코드를 아래와 같이 변경하면 하나의 파일로 두가지 버전을 관리 할 수 있다.

void memcpy(void* dst, void* src, size_t size)
{
    #ifdef DEBUG
    if( dst == NULL || src == NULL)

    {
        // 에러 발생 
    }
    #endif
     //~~ 복사 처리 //
}

ANSI  assert.h 헤더 파일의 assert라는 매크로를 이용하면 코드량을 훨씬더 줄일 수 있다.

void memcpy(void* dest, void* src, size_t size)
{
    assert(dst != NULL && src != NULL);
}

assert는 디버그만을 위한 매크로로서 인수로 false값을 받게되면 assert가 작동을 중단시킨다.
assert는 판매용과 디버그 버전 사이의 중대한 차이를 만들지 않도록 해야하므로 현재 프로그램의 메모리에 혼란을 줘서는 안된다.
보통의 프로그래머들은 위의 assert를 재정의해서 자신만의 assert를 사용하는데 주로 
assert가 발생한 파일과 라인 수를 출력 시킨다.

함수로 넘어오는 인자들은 모두 유효한 값인지 assert를 이용해 검사해주어야한다.


버그가 발생했을 때 억지로 정상적인 것 처럼 행동하도록 프로그래밍 할 수 있지만 이는 매우 위험한 방식이다. 따라서 assert를 이용해 프로그래머에게 경고해줌으로써 근본적으로 해결 할 수있도록 해야한다.

 


'이론 > [책]WRITINGSOLIDCODE' 카테고리의 다른 글

[1장]가상 컴파일러  (0) 2017.02.04