프로그래밍C 개발자

C 언어에서 오류 처리는 어떻게 구현되나요? setjmp/longjmp, errno, 그리고 오류 코드 반환의 차이점은 무엇인가요? 각 접근 방식을 언제 사용해야 할까요?

Hintsage AI 어시스턴트로 면접 통과

답변

C 언어에는 내장된 예외 처리 지원이 없으며, 오류 처리는 다음과 같은 방법으로 구현됩니다:

  1. 오류 코드 반환 (보통 함수의 반환 값으로) 예:

    int read_file(const char *name) { FILE *f = fopen(name, "r"); if (!f) return -1; // 오류 // ... fclose(f); return 0; // 성공 }
  2. 전역 변수 errno 사용 오류가 발생하면 표준 함수는 종종 전역 변수 errno를 설정합니다. 예:

    FILE *fp = fopen("nofile", "r"); if (!fp) { perror("파일 오류"); // errno는 원인을 정의합니다. }
  3. setjmp/longjmp — "예외"를 던지는 메커니즘 (실행 Context가 저장되고 복원됨) 복잡한 경우 (예: 다중 레벨 비상 종료)에 사용됩니다. 코드 복잡성을 증가시키고 자원 누수를 유발할 수 있어 드물게 사용됩니다.

    #include <setjmp.h> jmp_buf buf; if (setjmp(buf) == 0) { // ... longjmp(buf, 1); // if (setjmp(...))로 이동 } else { // 오류 처리 }
  • 오류 코드 반환 — 기본적인 방법, 간단하고 안전합니다.
  • errno — 라이브러리 함수에서 편리합니다.
  • setjmp/longjmp — 특정 사례(복잡한 라이브러리나 인터프리터)에 사용됩니다.

함정 질문

다음 코드의 출력은 무엇인가요?

#include <stdio.h> #include <setjmp.h> jmp_buf buf; void func() { longjmp(buf, 5); } int main() { int val = setjmp(buf); printf("val=%d ", val); if (val == 0) func(); return 0; }

답변:

  • 첫 번째 호출에서 setjmp는 0을 반환하고 func 함수가 호출됩니다.
  • 그 안에서 longjmp(buf, 5)가 실행되고, 실행이 다시 setjmp로 돌아가는데, 이번에는 5를 반환합니다.
  • 최종 출력:
    val=0
    val=5
    

주제에 대한 미숙지로 인한 실제 오류 사례


이야기 어떤 라이브러리에서는 오류 코드에 대한 수동 자원 정리 메커니즘을 구현했지만, 프로그래머가 콜백(through setjmp/longjmp)에서 반환 시 오류 처리를 간과하여 메모리 누수 및 파일 잠금이 발생했습니다.


이야기 네트워크 애플리케이션에서 소켓 작업 후 errno 체크를 놓쳤습니다. 이로 인해 이전 함수로부터의 오래된 잘못된 값이 남아 있어 잘못된 진단이 발생했습니다.


이야기 팀이 많은 오류 코드 반환 지점이 있는 복잡한 중첩 구조를 구현했지만, 반환 값(0/음수 값)에 대한 규칙을 준수하지 않았습니다. 일부 오류가 성공으로 해석되어 서비스의 예측할 수 없는 실패를 초래했습니다.