2 에러보고

GNU C의 많은 함수들은 에러 조건들을 조사하여 보고하며, 때로는 당신의 프로그램이 이러한 에러 조건들을 조사할 필요가 있다. 예를 들어, 당신이 입력파일을 열 때, 당신은 그 파일이 실제로 정확하게 열릴 수 있는지를 확정해야 하며, 에러메시지를 기록하고, 라이브러리 함수 호출에 실패하면 다른 적절한 조치를 취해야 한다.

이 장에서는 에러보고 도구들이 어떻게 작동하는지를 설명하겠다. 이 도구들을 사용하려면 프로그램에 헤더파일 'errno.h'를 포함하라.


2.1 에러 체크

대부분의 라이브러리 함수들은 실패할 때에 지정하는 특정한 값을 반환한다. 그 특정한 값이란 전형적으로 -1,널(null) 포인터, EOF라는 상수 등이다. 그러나 이러한 반환 값은 에러가 발생했다는 사실만을 지적해 준다. 어떤 종류의 에러가 발생했는지를 알려면, 변수 errno에 저장된 에러코드를 조사할 필요가 있다. 이 변수는 헤더파일 'errno.h'에 선언되어 있다.

변수 volatile int errno

변수 errno는 시스템 에러 숫자를 담는다. 당신은 errno의 값을 바꿀 수 있다. errno는 volatile로 선언되어 있으므로 부호취급자에 의해 바꿔질 수도 있다. 21.4 [취급자 정의하기] 참조. 그러나, 합당하게 씌어진 부호취급자는 errno의 값을 저장하기 때문에, 당신이 부호취급자를 적어야 할곳을 제외하고는 바뀔 가능성에 대해서 우려할 필요는 없는 것이다.

프로그램이 시작할 때 errno의 초기 값은 제로이다. 많은 라이브러리 함수들은 어떤 에러를 만날 때 그것을 제로가 아닌 값으로 만들도록 되어있다. 이러한 에러 조건은 각 함수에 기록되어 있다. 이 함수들이 성공했을 때에는 errno를 바꾸지 않는다; 그러므로, 당신은 호출이 실패했는지를 결정하지 않고서는 errno를 사용할 수 없다. 그것의 적절한 사용법은 각 함수에 기록되어 있다. 호출이 실패하게 되면, 당신은 errno를 검사할 수 있다.

많은 라이브러리 함수들은 다른 라이브러리 함수들을 호출하다가 실패한 결과로서 errno의 값을 제로 아닌 값으로 만들 수 있다. 당신은 어떠한 라이브러리 함수라도 그 함수가 에러를 반환 할 때에 errno의 값을 변경할 수 있음을 알아야 한다.

 
운용 노트 : ANSI C에서는 errno를 변수로서 다루기보다는 "변경 가능한 왼편 값"으로 규정하고, 그것이 매크로로 완성되는 것을 허용하고 있다. 예를 들면, 그것의 확장은 *_errno()와 같이 함수 호출을 포함할 수 있다. 사실상, 그것은 GNU 시스템 상에 존재하는 그대로이다. 비 GNU시스템 상에서 GNU 라이브러리는 특정한 시스템이 혀용 하는 모든 것을 할 수가 있다.

에러가 발생할 경우에 sqrt와 atan과 같이 완벽하게 적합한 값만을 반환하게 하는 몇몇 라이브러리 함수들도 있다. 이와 같은 함수들의 경우에는 만약 당신이 에러가 일어났는지를 체크하고자 한다면 함수를 호출하기 전에 지정된 방법으로 errno에 제로를 담아두고, 그런 다음에 그 값을 체크하게 된다. 모든 에러 코드는 부호 명칭을 갖고 있다; 그것들은 'errno.h'에 정의된 매크로이다. 그 명칭들은 'E'와 대문자 또는 구두점으로 시작된다. 당신은 이러한 명칭들을 예약된 명칭으로 생각하는 게 좋다. 1.3.3.[예약된 명칭] 참조.

에러코드의 값은 모두 양수의 정수이며 모두 별개로 구분된다. 단 하나의 예외가 있다: EWOULDBLOCK과 EAGAIN은 같은 경우이다. 이 값들은 분명한 것이므로, 당신이 switch 구문에서 라벨로 사용할 수 있다; 물론 EWOULDBLOCK과 EAGAIN을 그대로 사용할 수는 없다. 당신은 프로그램에서 이들 부호 정수의 특정한 값에 대해서 다른 가정을 해서는 안 된다.

errno의 값이 반드시 이러한 매크로들의 값과 일치할 필요는 없다. 왜냐하면, 어떤 라이브러리 함수들은 각각의 상황에 따라 다른 에러 코드를 반환할 수도 있기 때문이다. 특정한 라이브러리 함수에서만 의미를 갖도록 되어있는 값들은 이 안내서가 그 함수의 값으로 보여주는 바로 그 값이다. 비 GNU 체제에서는 대개의 경우 어떤 시스템이 유효하지 않은 포인터가 인수로서 주어질 때에는 EFAULT를 반환할 수 있다. 이것은 당신의 프로그램에서 버그의 결과로서 나타나고,GNU 체제에서는 일어나지 않기 때문에 우리는 개개의 함수를 기술할 때 EFAULT를 언급하지 않고 공간을 저장해 두었다.


2.2 에러 코드

에러코드 매크로는 헤더파일 'errno.h'에 정의되어 있다. 모든 에러코드 매크로는 정수의 상수 값으로 발전한다. 어떤 에러코드들은 GNU 체제상에서는 일어나지 않는다. 그러나 다른 체제에서 GNU의 라이브러리를 사용할 때에 발생할 수 있다.

매크로 int EPERM

허가되지 않은 작동; 파일의 소유자(또는 다른 자원)나 명령을 수행할 수 있는 특별한 권리를 가진 프로세스.

매크로 int ENOENT

그러한 파일이나 디렉토리 없음: 이것은 이미 존재하고 있을 걸로 예상한 파일이 없는 경우에 일어나는 "파일이 존재하지 않습니다"라는 에러이다.

매크로 int ESRCH

처리가 지정된 처리 ID와 합치되지 않는다.

매크로 int EINTR

가로채기 함수 호출; 발생한 비동기 신호와 호출의 방해된 종료. 이럴 경우에 당신은 다시 호출을 시도해 보라. 당신은 EINTR로 실패하기보다는, 함수들을 취급된 부호 다음에서 시작되도록 선택할 수 있다; 21.5 [가로채기 프리미티브] 참조.

매크로 int EIO

입출력 에러; 언제나 물리적인 입출력 에러에 사용됨.

매크로 int ENXIO

그런 장치나 주소가 없음. 시스템이 당신이 파일에서 설정한 장치를 사용하고자 하나 그러한 장치를 찾을 수 없었다. 이것은 장치파일이 잘못 인스톨되었거나, 물리적인 장치를 빠뜨렸거나 또는 컴퓨터와 제대로 부합되지 않았음을 의미한다.

매크로 int E2BIG

인수가 너무 길다; 실행함수에 의해서 실행되는 새로운 프로그램에 ( 23.5 [파일 실행하기] 참조) 주어진 인수가 너무 큰 메모리 공간을 사용할 때. 이러한 경우는 GNU체제에서는 생기지 않는다.

매크로 int ENOEXEC

유효하지 않은 실행파일 포맷. 이러한 조건은 실행함수에 의해 조사된다. 23.5 [파일 실행하기] 참조.

매크로 int EBADF

잘못된 파일 기록; 예를 들어, 닫혀진 파일을 기록하려고 하든지 쓰기 모드로 열려진 파일을 읽으려고 하는 경우(그 반대의 경우도)

매크로 int ECHILD

자식 프로세스(child process)가 없다. 이 에러는 자식 프로세스를 다루는 오퍼레이션을 사용했는데 다루기 위한 어느 프로세스도 존재하지 않을 때 발생한다.

매크로 int EDEADLK

교착상태 회피; 시스템 자원의 점유는 교착상태의 결과를 낳는다. 시스템이 모든 상황을 다 알아챌 거라고 보증하지 못한다. 이 에러는 당신이 운이 좋아서 시스템이 알아챈 것임을 의미한다; 시스템은 망설이고 있을 뿐이다. 8.11 [파일 교착] 참조.

매크로 int ENOMEM

이용할 메모리가 없음. 메모리 용량을 다 썼으므로 시스템이 더이상 메모리를 할당할 수 없다.

매크로 int EACCES

허용되지 않음; 파일이 시도하려는 작동을 허용하지 않는다.

매크로 int EFAULT

주소 오류; 유효하지 않은 포인터가 발견됨.

매크로 int ENOTBLK

어떤 상황에서 주어진 파일에 특별한 블록이 없는 경우. 예를 들면, 보통의 파일을 유닉스 파일 시스템에 마운트하려 하면 이 에러가 발생한다.

매크로 int EBUSY

시스템 자원 사용중; 분배될 수 없는 시스템 자원이 이미 사용중일 때, 예를 들어, 당신이 현재 마운트된 파일시스템의 루트에서 한 개의 파일을 지우려 할 때에, 이 에러를 만난다.

매크로 int EEXIST

파일이 존재: 새로운 파일로 만들겠다고 한 파일이 이미 존재한다.

매크로 int EXDEV

파일 시스템이 인지할 수 없는 영역에 부적당한 링크를 만들려고 시도할 때 이 에러메시지가 나온다. 이것은 당신이 링크를 사용할 때만 발생하지만 ( 9.3절 [Hard Links] 를 보라 ) 또, rename으로 파일을 재 명명할 때 발생하기도 한다. ( 9.6절 [Renaming Files] 를 보라)

매크로 int ENODEV

디바이스의 특별한 정렬을 하는 함수에 주어진 디바이스가 잘못된 타입이다.

매크로 int ENOTDIR

필요하다고 요청된 디렉토리가 존재하지 않을 때 발생.

매크로 int EISDIR

파일이 하나의 디렉토리이다; 쓰기(writing)위해 이 디렉토리를 열려고 시도할 때 이 에러는 발생한다.

매크로 int EINVAL

적합하지 않은 인수. 이것은 라이브러리 함수에 잘못된 인수를 주는 것과 같은 종류의 다양한 문제를 지적하는데 사용한다.

매크로 int ENFILE

지금 현재 프로세스에 너무 많은 파일이 오픈 되어서 더 이상 오픈할 수 없다. 복제된 기술자가 이 제한에 대하여 셈한다.

매크로 int ENFILE

전체 시스템에 열려져있는 너무 많은 개별파일들이 있다. 연결된 채널의 어떤 것이라도 파일 하나를 여는 것과 같이 센다.; 8.5.1절의 [연결된 채널]을 참조하라. 이 에러는 결코 GNU 시스템에서는 발생하지 않는다.

매크로 int ENOTTY

하나의 보통 파일에서 터미널 모드를 정하려 시도하는 것과 같은 부적합한 입출력 제어 오퍼레이션에 발생.

매크로 int ETXTBSY

현재 사용되고 있는 파일을 다시 읽거나 쓰기 위해 오픈 하려 시도할 때 발생 ("text fiel busy" 라고 한다.) 이것은 GNU시스템에서는 에러가 아니다; 텍스트는 필요하면 카피된다.

매크로 int EFBIG

파일이 너무 크다; 파일의 크기가 시스템이 허용하는 것 보다 더 크다.

매크로 int ENOSPC

디바이스에 공간이 남겨지지 않았다.; 파일에 쓰기 명령을 줬을 때 디스크가 가득 차서 공간이 남아있지 않으면 실패한다.

매크로 int EXPIPE

적합하지 않은 탐색 명령.( pipe에서 처럼 )

매크로 int EROFS

읽기 전용으로 된 어떤 파일시스템에 무언가를 수정하려고 시도할 때

매크로 int ENLINK

너무 많이 연결.; 하나의 단일한 파일의 링크 수가 너무 길다. 재 명명하다 이미 할 수 있는 것보다 많은 링크를 가진 한 파일을 재 명명하면 이 에러의 원인이 된다. ( 9.6절 [파일 재 명명] 참조)

매크로 int EPIPE

부러진 파이프; 다른 파이프의 끝에서 프로세스를 읽는 것은 불가능하다. 모든 라이브러리 함수는 SIGPIPE로 일반화된 에러코드를 반환 한다. 이 신호는 만약 처리되지 않거나 막아지지 않으면 그 프로그램을 멈추게 한다. 그러므로 당신의 프로그램이 처리되거나 블록된 SIGPIPE를 갖지 않으면 항상 EPIPE가 보일 것이다.

매크로 int EDOM

도메인 에러; 인수의 값이 정의된 함수를 지나 도메인에게 전달되지 않았을 때 수학적 함수에 의해 사용된다.

매크로 int ERANGE

범위 에러; 결과 값이 오버플로우나 언더플로우로 인해 표현되지 않을 때 수학적 함수에 의해 사용된다.

매크로 int EAGAIN

자원을 일시적으로 사용할 수 없다. 그 호출은 나중에 당신이 다시 시도 할 수 있도록 한다. 오직 분기점에서 이러한 이유로 EAGAIN에러 코드를 반환 한다.

매크로 int EWOULDBLOCK

비블록화 모드로 정해진 어떤 대상에 블록을 시도하려 하는 오퍼레이션에 대해 발생.
 
이식성 : 4.4BSD와 GNU에서 EWOULDBLOCK 와 EAGAIN은 같다. BSD초기 버전에서는 이것이 두 개의 독립적 코드로서 EWOULDBLOCK는 비블록화 모드로 정해진 대상에 블록을 시도하는 입출력 오퍼레이션을 지적하는데 사용하고 EAGAIN은 에러의 다른 종류에 사용했다
매크로 int EINPROGRESS
비블록화 모드로 선택된 대상에 일으킨 완전하지 않은 오퍼레이션에 대해 발생. 어떤 함수들은 항상, 블록을( connect처럼 ; 11.8.1절의 [연결]을 참조) 결코 반환하지 않아야 한다.EWOULDBLOCK 대신에 그들은 어떤 시간을 취하고( 즉 일정 시간이 지난 후) 시작되는 오퍼레이션을 지적하기 위해 EINPROGRESS를 반환 한다. 그 호출에 EALREADY가 반환 되어 완전하기 전에 그 대상을 다루려 시도할 때.

매크로 int EALREADY

한 오퍼레이션이 비블록화 모드의 선택을 가진 대상에 이미 진행중이다.

매크로 int EALREADY

소켓을 요청했을 때 지정된 소켓이 존재하지 않는다.

매크로 int EDESTADDRREQ

목적 주소가 그것이 필요한 소켓 오퍼레이션에 공급될 수 없다.

매크로 int EMSGSIZE

소켓에 보낸 메시지의 크기가 지원되는 최대 크기보다 크다.

매크로 int EPROTOTYPE

그 소켓 타입이 요청된 통신 프로토콜에서 지원하지 않는다.

매크로 int ENOPROTOOPT

당신은 소켓에 의해 사용되어지고 있는 특별한 프로토콜에서 이해할 수 없는 소켓옵션을 지정하였다. ( 11.11절의 [Socket Options]를 참조)

매크로 int EPROTONOSUPPORT

그 소켓 도메인은 요청한 통신 프로토콜을 지원하지 않는다. ( 아마도 요청된 프로토콜이 완전히 부적합하다.) 11.7.1절의 [Creating a Socket]를 보라.

매크로 int ESOCKTNOSUPPORT

그 소켓타입을 지원하지 않는다.

매크로 int EOPNOTSUPP

당신이 요청한 그 오퍼레이션을 지원하지 않는다. 어떤 소켓함수는 소켓의 모든 타입들에서 이해할 수 없고 다른 것들은 모든 통신 프로토콜을 충족시키지 못할 것이다.

매크로 int EPFNOSUPPORT

당신이 요청한 소켓통신 프로토콜 부류들은 지원하지 않는다.

매크로 int EAFNOSUPPORT

소켓을 위하여 지정된 주소의 부류들이 지원되지 않는다; 그 주소가 소켓에서 사용되는 프로토콜과 일치하지 않는 것이다. 11장[Sockets] 참조하라.

매크로 int EADDRINUSE

요청된 소켓주소가 이미 사용중이다. 11.3절 [Socket Addresses] 를 보라.

매크로 int EADDRNOTAVAIL

요청된 소켓주소가 유용하지 않다.; 예를 들어 당신이 소켓이름으로 주려고 시도한 것이 로컬 호스트 이름과 맞지 않다. 11.3절[Socket Address] 를 보라.

매크로 int ENETDOWN

소켓 오퍼레이션이 네크웍 다운이 이유가 되어 실패했다.

매크로 int ENETUNREACH

소켓 오퍼레이션이 호스트가 포함하고 있는 subnet에 도달할 수 없어서 실패했다.

매크로 int ENETRESET

원격 호스트가 파괴되었기 때문에 네트웍 연결을 다시 지정한다.

매크로 int ECONNABORTED

네트웍 연결이 실패하였다. 네트웍 연결이 단절되었는데 그 이유는 원격 시스템이 재부팅 하거나 아니면 복구할 수 없는 프로토콜 위반인 경우처럼 로컬 호스트의 제어를 벗어난 것이 이유이다.

매크로 int ENOBUFS

입출력 오퍼레이션을 위한 커널의 버퍼들이 모두 사용중이다.

매크로 int EISCONN

당신은 이미 연결된 소켓을 다시 연결하려 시도하고 있다. 11.8.1절[Connectings] 를 보라.

매크로 int ENOTCONN

그 소켓은 어느 것과도 연결할 수 없다. 당신이 첫째로 데이터의 목적지를 정하지 않고 한 소켓을 통해 데이터를 전송하려 할 때 이 에러가 발생한다.

매크로 int ESHUTDOWN

그 소켓은 이미 폐쇄되었다.

매크로 int ETIMEDOUT

정해진 타임아웃을(timeout) 갖은 소켓 오퍼레이션이 정해진 시간 동안 응답을 받지 못했다.

매크로 int ECONNREFUSED

원격 호스트가 네트웍 연결에 대한 허용을 거절하였다. (특별히 요청된 서비스가 실행되지 않기 때문에)

매크로 int ELOOP

파일이름을 탐색하려는데 너무 많은 수준의 기호연결(sysbolic links)이 있다. 이것은 종종 기호연결의 한 주기를 가리킨다.
참고로 sysbolic links는 데이터베이스 프로그램과 스프레드시트 등과 같은 프로그램들 사이에서 상호 간의 원활한 데이터 교환을 위해 사용되는 데이터 파일의 형식이래요.

매크로 int ENANETOOLONG

파일 이름이 너무 길거나( PATH_MAX보다 더; 27.6절 [Limits for Files]를 참조하라) 호스트 이름이 너무 길다.( gethostname 이나 sethostname에 있는; 26.1절 [Host Identification])

매크로 int EHOSTDOWN

요청된 네트웍 연결을 위한 원격 호스트가 다운이다.

매크로 int EHOSTUNREACH

요청된 네트웍 연결을 위한 원격 호스트에 도달할 수 없다.

매크로 int ENOTEMPTY

빈 디렉토리라고 예상했던 곳이 비어있지 않다. 특별히 이 에러는 당신이 디렉토리를 지우려 시도할 때 발생한다.

매크로 int EUSERS

파일할당 시스템이 너무 많은 유저로 인해 혼란하다.

매크로 int EDQUOT

사용자의 디스크 할당이 초과되었다.

매크로 int ESTALE

맛이간 NFS 파일 핸들. 이것은 파일 시스템이 서버 호스트 상에서 재 정렬한 것에 기인한 것으로 NFS 시스템 안의 내부적 혼란을 지적한다.

매크로 int ERENOTE

이미 NFS 마운트 파일로 지정된 한 파일을 한 원격 파일 시스템이 NFS 마운트로 만들려 시도할 때 발생. (이것은 운영체제상의 에러이지만 우리는 이 에러를 불가능한 코드로 만들고 GNU시스템 상에서 작업하기를 기대하는 것이다.)

매크로 int ENOLCK

유용한 락이 아니다. 이것은 파일 락킹 함수들에 의해 사용된다. 8.11절 [File Locks] 참조. 이 에러는 GNU 시스템에서는 결코 발생하지 않는다.

매크로 int ENOSYS

함수가 이행되지 않았다. 어떤 함수들은 정의된 옵션이나 명령들이 어떤 것에서도 지원되지 않는 것이 있다. 만약 당신이 요청한 함수에서 이런 에러를 얻는다면 그것들은 지원되지 않는 것이다.

매크로 int EBACKGROUND

GNU 시스템에서 어떤 오퍼레이션의 호출자가 터미널의 전면처리 그룹에 없을 때 서버지원 프로토콜에 이 에러가 반환된다. 사용자들은 보통 이 에러를 보지 못하는데 왜냐하면 함수들은 SIGTTIN이나 SIGTTOU신호로 해석하여 읽고 쓰기 때문이다. 24장[Job Control] 를 프로세스 그룹과 이들은 신호의 정보를 위해 보라.

매크로 int ED

경험 있는 사용자는 무엇이 잘못인지 알 것이다.

매크로 int EGREGIOUS

당신이 무엇을 했지?

매크로 int EIEIO

집에 가서 따뜻하고, 신선한 한잔의 우유를 마셔라

매크로 int EGRATUITOUS

이 에러 코드는 목적이 없다.


2.3 에러 메시지

라이브러리에는 당신의 프로그램이 라이브러리를 호출하다가 실패할 때에 흔히 일어나는 에러를 메시지로 보낼 수 있도록 하는 함수와 변수들이 있다. 함수 strerror와 perror는 특정한 에러코드로 정형화된 에러메시지를 보낸다; 변수 program_invocation_short_name은 에러가 난 프로그램의 명칭을 쉽게 찾도록 해준다.

함수 char * strerror (int errnum)
strerror 함수는 인수 errnum을 받아서 에러코드(2.1 [에러 체크] 참조)를 문자열을 기술한 에러메시지로 그려낸다. 반환 값은 이 문자열의 포인터이다. 인수 errnum의 값은 보통 변수 errno에서 전달된다. 당신은 함수 strerror가 반환한 문자열을 변형시켜서는 안 된다. 또한, 만약 당신이 strerror를 계속 호출하게 되면, 그 문자열은 덧씌워질 것이다. (그러나 어떠한 라이브러리 함수도 당신이 알지 못하게strerror함수를 호출하지 않음은 믿어도 좋다.)
함수 strerror는 헤더파일 'string.h'에 선언되어 있다.

함수 void perror (const char *message)

이 함수는 에러메시지를 문자열 stderr에 기록한다; 7.2 [표준 문자열] 참조. 만약에 널(null) 포인터라든지 공백 문자열인 message를 써서 perror를 호출하게 되면, perror는 errno에 해당하는 에러메시지를 기록하고, 뒤에 새로운 행을 추가한다. 그렇지 않고 널(null)이 아닌 인수 message를 쓰게 되면,perror는 에러메시지 앞에 해당 문자열을 갖다둔다. 거기에는 errno에 해당하는 에러문자열로부터 메시지를 분리하기 위해서 콜론(:)과 공백문자를 추가한다. 함수 perror는 'stdio.h'에 선언되어 있다.

strerror와 perror는 어떤 에러코드가 주어지든지 간에 같은 메시지를 만들어낸다; 규정된 텍스트는 시스템에 따라 변한다. GNU 체제에서는 메시지가 아주 짧다; 두줄 이상의 메시지나 삽입된 줄은 아예 없다. 각 에러메시지는 대문자로 시작하며 구두점은 쓰지 않는다.

 
호환성 노트 : 함수 strerror는 ANSI C의 새로운 특성이다. 과거의 많은 C언어 체제에서는 이 함수가 제공되지 않았다. 터미널로부터 입력을 읽어들이지 않는 많은 프로그램들은 어떤 시스템 호출이 실패하게 되면 종료되도록 만들어져 있다. 전통적으로, 그와 같은 프로그램으로부터 나오는 에러메시지는 디렉토리는 기술하지 않고 그 프로그램의 명칭만으로 시작한다. 당신은 그 명칭을 변수 program_invocation_short_name에서 찾아볼 수 있다; 완전한 파일 명칭은 변수 program_invocation_name에 저장된다:

변수 char *program_invocation_name;

이 변수의 값은 현재 진행중인 프로그램 실행을 시작하는데 사용되는 명칭이다. 그것은 argv[0]과 동일하다. 이것이 반드시 유효한 파일명칭을 필요로 하는 것이 아님을 주의하라; 흔히 유효한 파일명칭은 디렉토리 명칭을 담고있지 않다. 22.1 [프로그램 인수] 참조.

변수 char * program__invocation__short__name

이 변수의 값은 현재 처리중인 프로그램을 부르는 데 사용되는 명칭으로서 디렉토리 명칭이 제거된 것이다.(말하자면, 이것은 program_invocation_name에서 마지막 슬래쉬까지를 빼버린 것과 동일하다.)

라이브러리 초기화 코드는 메인 함수를 호출하기 전에 이 두 개의 변수를 구축(構築)한다.

 
운용 노트 : 이 두개의 변수는 GNU의 확장이다. 만일 당신이 GNU 이외의 라이브러리를 쓰고 싶으면, 메인 함수에서 argv[0]의 값을 저장한 다음에 당신이 손수 디렉토리의 명칭을 제거하면 된다. 우리는 메인 함수에서 명시적인 표현을 하지 않고서 그 자체에서 에러 보고용 서브루틴을 담고 있도록 하기 위하여 이와 같은 확장을 하게 되었던 것이다.

파일을 제대로 열지 못하고 실패를 하게 되는 예를 들어보기로 하자. 함수 open_sesame은 읽기 모드로 주어진 파일을 열고 성공하면 문자열을 반환한다. 라이브러리함수 fopen은 파일을 열 수 없을 때 널(null) 포인터를 반환한다. 이 같은 상황에서,open_sesame은 함수 strerror를 사용하는 적절한 에러 메시지를 만들어내고서 프로그램을 종료한다. 만약 우리가 strerror에 에러 코드를 보내기 전에 다른 어떤 라이브러리를 호출하고자 한다면, 우리는 그것을 지역 변수에 저장하여야만 한다. 왜냐하면, 그 다른 어떤 라이브러리 함수들이 동시에 errno를 덧씌울 것이기 때문이다.

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*으음..함수의 형태로 FILE을 선택할 수도 있었군*/
FILE * open_sesame (char *name)
/*요건 인수로 문자형 포인터를*/
{
FILE *stream;
/*우잉? 이건 파일명칭이 포인터로? 흐흐흐..교과서적인 내용*/
errno = 0; /*요건 뭔가 이상타? errno를 int라고 선언하지 않아도 되남?*/
stream = fopen (name, "r"); /*파일을 읽기 모드로 열고*/
if (stream == NULL) /*파일이 존재하지 않으면?*/
{
fprintf (stderr, "%s: Couldn't open file %s; %s\n",
program_invocation_short_name, name, strerror (errno));
/*아아! fprintf 함수는 (1) 무엇을 (2)어디에서 읽어서 (3)어딘가에 쓰는 것 3부분으로 구성되네요! 이 몸은 이런 건 외울 수가 없어요==건망증==프로그램 짜다가 필요하면 그때 보지요*/
exit (EXIT_FAILURE); /*난 exit와 return의 차이도 몰러, 흑*/
} else /*파일이 존재하면?*/
return stream;
}
}