본문 바로가기
개발

goto 대신에 do { ... } while (false)를 사용한 에러처리

by 솜씨제이 2010. 3. 25.
C/C++ 코딩을 하다보면 흔히 아래와 같은 에러처리 코드를 만나게 된다.
...
if (!condition1)
    goto cleanup;
...
if (!condition2)
    goto cleanup;
...
if (!condition3)
    goto cleanup;
...
if (!condition4)
    goto cleanup;
...
cleanup:
// 메모리 해제등의 정리 작업
고급 언어에서는 goto를 사용하지 말라고 많이 하고 실제 goto의 사용이 스파게티 코드를 만드는 경우가 많기 때문에 사용하지 않는 것이 좋지만 C/C++에서는 finally를 지원하지 않기 때문에 위와 같은 코드는 묵인해주는 경우가 많다. 그래도 goto를 피하고 싶기 때문에 아래처럼 하기도 한다.
...
if (!condition1)
{
    // 메모리 해제등의 정리 작업1
    return;
}
...
if (!condition2)
{
    // 메모리 해제등의 정리 작업2
    return;
}
...
if (!condition3)
{
    // 메모리 해제등의 정리 작업3
    return;
}
...
if (!condition4)
{
    // 메모리 해제등의 정리 작업4
    return;
}
...
이렇게 하면 코드 길이가 길어지고 정리 작업이 변경되거나 늘어나면 하나 하나 수정해줘야 하는 문제가 있다.
...
if (condition1)
{
    ...
    if (condition2)
    {
        ...
        if (condition3)
        {
            ...
            if (condition4)
            {
                ...
            }
        }
    }
}
// 메모리 해제등의 정리 작업
이렇게 바꾸더라도 역시 코드 길이가 길고 깊이가 깊어져서 읽기 어려운 단점이 있다.

do
{
    ...
    if (!condition1)
        break;
    ...
    if (!condition2)
        break;
    ...
    if (!condition3)
        break;
    ...
    if (!condition4)
        break;
    ...
} while (false);
// 메모리 해제등의 정리 작업
이렇게 하면 어떨까? goto 문을 사용한 경우와 비교해볼 때 코드의 길이도 차이가 거의 없고 읽기도 쉽다. while (true) { ... }을 사용할 수도 있지만 아무래도 while (true)를 사용할 경우 실수하면 무한루프에 빠질 염려가 있다. 사실 이걸 고민한 건 아래 코드를 컴파일할 필요가 있었는데 해당 구문에 소멸자가 있는 클래스 객체를 사용하고 있다고 컴파일 안 되는 문제가 있었다.
__try
{
    ...
    if (!condition1)
        __leave;
    ...
    if (!condition2)
        __leave;
    ...
    if (!condition3)
        __leave;
    ...
    if (!condition4)
        __leave;
    ...
}
__finally
{
    // 메모리 해제등의 정리 작업
}
클래스 객체를 사용하지 않는 방법으로 처리할 수도 있었겠지만 아무래도 비표준 코드를 쓰기 싫기도 해서 생각하다보니 goto 보다는 do { ... } while (false)가 더 나아 보여서 do ( ... } while (false)로 수정했다. 사실 goto 문을 쓴다고 해서 큰 일이 나는 것은 아니니 goto 문을 사용해도 그만이다. 그리고 C/C++에서 finally를 지원하면 더 좋지 않을까 싶기도 하다.

댓글