C입출력과 파일

assert와 errno

`assert`로 프로그램 불변식을 검사하고, `errno`와 `perror`로 표준 라이브러리 오류를 진단하는 방법을 정리합니다.

마지막 수정 2026년 3월 26일

기본 패턴

c
#include <assert.h>
#include <errno.h>
#include <stdio.h>

// assert — 조건이 거짓이면 즉시 abort
assert(ptr != NULL);

// errno — 표준 라이브러리 함수 실패 후 오류 코드 확인
FILE *fp = fopen("no_file.txt", "r");
if (!fp) {
    perror("fopen");   // "fopen: No such file or directory"
}

설명

assert — 개발 중 불변식 검사

c
#include <assert.h>

int divide(int a, int b) {
    assert(b != 0);   // 조건이 0이면: 파일명, 줄 번호와 함께 abort
    return a / b;
}

// NDEBUG 매크로가 정의되면 assert는 완전히 제거됨
// 릴리스 빌드: gcc -DNDEBUG file.c
// → assert는 런타임 비용 0

// 정적 어서션 (컴파일 타임 검사, C11)
_Static_assert(sizeof(int) == 4, "int는 4바이트여야 합니다");

errno — 표준 라이브러리 오류 코드

많은 표준 함수는 실패 시 전역 변수 errno에 오류 코드를 기록합니다.

c
#include <errno.h>
#include <string.h>   // strerror

// errno는 성공 시에도 변경될 수 있으므로
// 실패를 확인한 직후 errno를 읽어야 함
errno = 0;                              // 선택적으로 먼저 초기화
FILE *fp = fopen("missing.txt", "r");
if (!fp) {
    int saved = errno;                  // 즉시 저장
    fprintf(stderr, "오류 코드: %d\n", saved);
    fprintf(stderr, "오류 메시지: %s\n", strerror(saved));
}

perror — errno 기반 메시지 출력

c
// perror("prefix") → "prefix: errno 메시지\n"
FILE *fp = fopen("data.txt", "r");
if (!fp) {
    perror("파일 열기 실패");
    // 예: "파일 열기 실패: No such file or directory"
    return 1;
}

// strerror — 오류 코드를 문자열로 반환 (perror 대신 직접 포맷할 때)
fprintf(stderr, "[%d] %s\n", errno, strerror(errno));

자주 보이는 errno 값

c
#include <errno.h>

ENOENT    // 2  — 파일/디렉토리 없음
EACCES    // 13 — 권한 없음
EINVAL    // 22 — 잘못된 인수
ENOMEM    // 12 — 메모리 부족
EEXIST    // 17 — 이미 존재
ENOBUFS   // 이식성 없음, POSIX 한정

빠른 정리

항목역할
assert(expr)expr이 거짓이면 abort + 오류 위치 출력
NDEBUG정의 시 assert 완전 비활성화 (릴리스 빌드)
_Static_assert(expr, msg)컴파일 타임 조건 검사 (C11)
errno표준 라이브러리 함수 실패 후 오류 코드
perror(prefix)errno 기반 오류 메시지를 stderr에 출력
strerror(n)오류 코드 n을 설명 문자열로 변환

주의할 점

assert는 런타임 오류 처리가 아닌 개발 중 불변식 검사용입니다. 사용자 입력 검증이나 프로덕션 오류 처리에는 사용하지 마세요. 릴리스 빌드에서 NDEBUG로 제거되면 그 안의 부작용 코드도 함께 사라집니다.

errno는 성공한 함수 호출 후에도 값이 바뀔 수 있습니다. 실패를 확인한 직후 즉시 읽어야 정확한 오류를 알 수 있습니다.

참고 링크

2 sources