POSIX getline выделяет или увеличивает буфер через переданный указатель, и этот буфер принадлежит вызывающему с первого же вызова. В том числе после вызова, который вернул -1. Спецификация оставляет освобождение приложению, а man-страница 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 должны начинаться с нулевого указателя и нуля либо с буфера из malloc с его настоящим размером. Массив на стеке не годится, потому что getline может передать его в realloc.
Чаще всего я вижу free(line) внутри ветки ошибки и ни одного на пути конца файла.
