당연하지만 간과하는 size_t ssize_t
IO 함수를 사용함에 있어서 그 근간이 되는 것은 read
와 write
함수이다.
이 함수는 모두 ssize_t
를 반환하는데, 보통은 너무나 축복받은 환경에 있기 때문에 저게 왜 ssize_t
인지 모르는 경우가 많다.
size_t
는 size를 나타내기 위한 type으로 보통의 32bit machine에서는 32bit, 즉 unsigned int
로 되어있다. 가장 유명한 sizeof
라는 연산자가 반환하는 값을 담기 위한 type으로 보면 되는데 이 역시 크기를 의미하므로 많은 IO 함수에서 사용된다.
ssize_t
는 signed size type
으로 보통의 32bit machine에서는 간단히 말해 int
다. IO 함수의 반환값으로 많이 사용되는데 그 이유는 해당 IO 함수의 실패를 알려주기 위해서이다.
errno
라는 개념은 표준 C 함수 수행도중 오류가 발생했을 때 그 함수는 -1을 반환하고 errno라는 전역변수에 어떤 에러가 발생했는지에 대한 값을 넣는 구조의 개념이다.
그래서 주로 perror
를 통해 이 errno
이 의미하는 문자열을 보는데, read
나 write
함수는 실패할 경우에 -1을 반환해야하기 때문에 ssize_t
를 반환 type으로 쓰는 것이다.
간단히 네트워크 환경으로 예를 들어보면, 내가 읽으려는 socket
이 닫히면 read
는 -1을 반환한다.
동일한 개념으로 write
역시 쓰고자 하는 socket
이 닫히면 -1을 반환하는 것이다.
이렇게 socket
의 닫힘을 깨닫고 해당 socket 관련 작업 내역(context)을 제거해주어야 하는데 보통은 안 그런다.
어차피 학교에서 짜는 정도이면 네트워크가 그리 끊어질 일도 없고(wired network에 전원 걱정 없는 server이니) 프로그램을 껐다 켜기 쉬우니까.
그래서 연구실 아르바이트할 때 작성했던 io 함수들이 size_t
를 반환하도록 설계되어있다. (내가 그랬다 ㅠㅠ)
이게 buffered stream이면 문제가 복잡해진다. read
는 불가능해도 내부 buffer에 남아있는 것에서 자료를 뺄 수는 있으니까. write
역시 내부의 자료를 보존해줄지 초기화해줄지를 고민해야하지만 Java의 Exception 에 익숙해져있다보니 막상 c로 설계를 할 때는 그런걸 고민을 하나도 안해버렸다 […]