C 언어에서 오류 처리는 항상 개발자의 과제였습니다. 표준 라이브러리에는 예외가 없으며, 오류는 반환 코드 또는 글로벌 변수 errno를 통해 반환됩니다(사용 시작 — 1970년대 UNIX, 이후 POSIX 및 ANSI C). 이러한 메커니즘은 오늘날에도 비정상적인 상황에서 흐름 제어를 위해 사용됩니다.
표준 함수(파일 작업, 메모리 할당, 문자열 함수)를 사용할 때 오류는 특별한 제어 없이는 감지되지 않을 수 있습니다. 잘못된 처리 — 반환 코드 무시, errno 해석 오류, 리소스 정리 부족 — 는 프로그램의 잘못된 동작, 충돌 및 취약점으로 이어질 수 있습니다.
올바른 오류 처리는 반드시 함수가 반환하는 값을 분석하고, 실패 직후에만 errno를 사용하며, 오류에 대한 정보 제공이 필요합니다. 반환 코드는 내부 함수에 선호되며, 글로벌 부작용 없이 처리를 가능하게 합니다. errno는 시스템 호출 및 표준 라이브러리 함수와 함께 더 자주 사용됩니다. 각 잠재적으로 위험한 작업 후에 반환 값을 분석하고, 글로벌 상태(errno)는 중간 호출로 덮어써지지 않아야 합니다.
코드 예:
#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "오류: %s ", strerror(errno)); } return f; }
주요 특징:
사용자 정의 함수에서 오류를 위로 전달하려면 errno를 사용할 수 있습니까?
아니요, errno는 표준 라이브러리 및 시스템 호출에만 사용되도록 설계되었습니다. 그것은 전역적이며 어떤 시점에서든 덮어쓸 수 있으므로 자체 함수에는 적합하지 않습니다.
각 함수 호출 전에 errno를 설정해야 합니까?
아니요, 그러나 변경 사항을 분석할 계획이라면 호출 전에 errno(예: 0으로) 초기화하는 것이 좋습니다. 모든 함수가 성공 시 errno를 변경하는 것은 아니며 오류 시에만 변경합니다.
eno = 0; ... 위험한 함수 호출 ...
모든 함수 호출 후 errno를 신뢰할 수 있습니까?
오류 발생 시 명시적으로 설정한다고 표준이 정하고 있는 함수에 대해서만 가능합니다. 많은 표준 라이브러리 함수는 성공 시 errno를 변경하지 않습니다. 문서가 당신의 친구입니다.
결과를 확인하지 않고 파일을 열고, 오류가 분석되지 않으며, 파일이 없을 때 프로그램이 잘못 작동합니다:
장점:
단점:
모든 중요한 함수 후에 결과를 확인하고, 오류 발생 시 strerror(errno)로 상세한 메시지를 출력하며, 올바르게 실행을 종료합니다:
장점:
단점: