본문 바로가기
모던 C 언어/C언어 예외처리(Try-Catch)

1. Goto를 사용한 에러핸들링

by 커널패닉 2021. 12. 26.
반응형

프로그래밍을 하다보면 발생 가능한 에러들에 대해서 신경을 써야 한다. 버그는 신중한 개발자가 좋은 코드를 짠다면 최소화 할 수 있는 반면, 에러는 좋은 코드에서든 나쁜 코드에서든 발생한다. 결국 우리는 에러가 발생할 수 있다는 사실을 받아들이고, 이를 어떻게 처리할 지 생각해야 한다. 다음은 흔히들 마주칠 수 있는 에러들의 예시이다.

  • 파일 열기
  • 파일 입출력
  • 소켓 통신
  • 메모리 할당

C언어 이후에 개발된 언어들은 대부분 Try-Catch 혹은 이와 유사한 구문을 지원한다. Try-Catch 문에 익숙하지 않다면 아래 Java 프로그램의 예시를 살펴보자.

더보기

다음은 파일을 열고, 내용을 한줄씩 출력하는 Java 프로그램이다.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        try{
            File file = new File("helloworld.txt");
            FileReader filereader = new FileReader(file);
            BufferedReader bufReader = new BufferedReader(filereader);

            String line = "";
            while((line = bufReader.readLine()) != null){
                System.out.println(line);
            }

            bufReader.close();
        }catch (FileNotFoundException e) {
            // 파일 Open 실패 시  발생
            System.out.println("File Not Found Error");
        }catch(IOException e){
            // IO 실패 시 발생
            System.out.println("IO Error");
        }
    }
}

Java에서는 Try/Catch를 사용해서 발생하는 에러를 처리한다. 위의 예제에서는 에러 발생시에 간단히 로그를 출력했지만, 없는 파일을 생성하거나, 이미 열려있는 리소스를 정리하는 등의 작업들을 수행할 수 있다.

C에는 Try/Catch가 없다. 일반적으로 C에서는 Try/Catch 대신 if 문으로 에러 발생 여부를 체크한다. 다음은 파일을 열고, 내용을 한 줄씩 출력하는 프로그램이다.

#include <stdio.h> 

int main() {
    char line[1024];

    FILE *fp = fopen("helloworld.txt", "r");
    if (fp == NULL) {
        printf("File Not Found Error\n");
        return 1;
    }

    char *ret = NULL;
    do {
        ret = fgets(line, sizeof(line), fp);
        if (ferror(fp)) {
            printf("IO Error\n");
            fclose(fp);  /* fclose로 열린 파일을 close 해야 한다. */
            return 1;
        }
        printf("%s\n", line);
    }while(ret);

    fclose(fp);

    return 0;
}

Java 프로그램과 동일하게 동작하는 코드이다. 위의 예에서 보이듯이 C에서도 if 문을 활용해서 예외처리가 가능하다. 하지만 if 문을 사용하면 fclose가 두 군데에서 호출되는 것처럼 리소스 해제 등의 정리 작업이 별도로 이뤄져야 한다. 지금은 열려 있는 파일을 닫기만 하면 되지만, 복잡한 장치, 코드를 정리하게 된다면 중복되는 코드는 더 많고 복잡해 질 것이다. 이 때 사용 가능한 방법이 Goto 문이다. Goto문을 사용하면 위의 코드가 아래와 같이 정리된다.

#include <stdio.h> 

int main() {
    char line[1024];

    FILE *fp = fopen("helloworld.txt", "r");
    if (fp == NULL) {
        printf("File Not Found Error\n");
        return 1;
    }

    char *ret = NULL;
    do {
        ret = fgets(line, sizeof(line), fp);
        if (ferror(fp)) {
            printf("IO Error\n");
            goto out;
        }
        printf("%s\n", line);
    }while(ret);

out:
    fclose(fp); /* 리소스 정리가 한 군데에서 이뤄진다. */

    return 0;
}

리소스 정리가 한 군데에서 이뤄지기 때문에 코드의 중복과 휴먼 에러에 의한 정리 누락을 예방할 수 있다. 위의 예시는 아주 간단한 코드이고 실전에서는 goto 문을 중첩으로 쌓아서 단계별 에러 핸들링을 할 수 있다. goto 문의 중첩을 활용한 에러핸들링은 다음 포스트에서 살펴보자.

반응형