POSIX getline은 넘겨받은 포인터를 통해 버퍼를 할당하거나 키우며, 그 버퍼는 첫 호출부터 호출자의 것입니다. -1을 반환하는 호출도 예외가 아닙니다. 명세는 해제를 애플리케이션에 맡기고, Linux 매뉴얼 페이지는 getline이 실패하더라도 버퍼를 해제해야 한다고 직접 적어 둡니다.
따라서 루프에는 해제가 정확히 한 번, 루프가 끝난 뒤에 있습니다. 끝난 이유와는 상관없습니다.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *line = NULL;
size_t cap = 0;
ssize_t n;
long lines = 0;
while ((n = getline(&line, &cap, stdin)) != -1)
lines++;
if (ferror(stdin))
perror("getline");
free(line);
printf("%ld\n", lines);
return 0;
}
여기서 두 가지가 따라옵니다. 첫째, -1은 파일 끝과 읽기 오류를 모두 뜻하므로 둘을 구분하려면 ferror나 feof를 봐야 하고, 어느 경우든 line을 누가 해제하는지는 바뀌지 않습니다. 둘째, line과 cap은 널 포인터와 0으로 시작하거나, malloc으로 얻은 버퍼와 그 실제 크기로 시작해야 합니다. 스택 배열은 안 됩니다. getline이 그것을 realloc에 넘길 수 있기 때문입니다.
가장 자주 보는 실수는 오류 분기 안에만 free(line)이 있고 파일 끝 경로에는 없는 경우입니다.
