Тестовый жгут, показывающий проблему.
Разница между этим кодом и OP заключается в том, что всегда отображается статус errno
.
Когда происходит нехватка памяти, устанавливается errno
, но getline()
возвращает длину, превышающую capacity
, что очень странно, а не -1.
Если это соответствует или нет, я оставляю на вашу интерпретацию ниже. ИМО не соответствует. Я ожидаю возвращаемого значения -1, если errno
установлено из-за getline()
по какой-либо причине, помимо ferror()
или отсутствия чтения в конце файла.
Я подозреваю, что проблема связана с отложенным выделением памяти.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха getline()
и getdelim()
возвращают количество прочитанных символов, включая символ-разделитель, но не включая завершающий нулевой байт ("\0"). Это значение можно использовать для обработки встроенных нулевых байтов в прочитанной строке.
Обе функции возвращают -1 при ошибке чтения строки (включая условие конца файла). В случае ошибки устанавливается errno для указания причины.
ОШИБКИ
EINVAL Неверные аргументы (n или lineptr имеет значение NULL, или поток недействителен).
ENOMEM Не удалось выделить или перераспределить буфер строки.
Код также экспериментирует с CR/LF против LF, но это не представляется актуальным.
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
int djtest(unsigned sh, unsigned long long a, bool crflag) {
printf("sh:%2u a:%12llu crlf:%d ", sh, a, crflag);
FILE *stream = fopen("test.bin", "wb");
if (stream == NULL) {
return printf("error fopen(wb)\n");
}
char buf[1024 * 1204];
memset(buf, 'a', sizeof buf);
while (a > 0) {
unsigned long long m = a;
if (m > sizeof buf) m = sizeof buf;
size_t y = fwrite(buf, sizeof *buf, (size_t) m, stream);
if (y != m) {
return printf("error fwrite\n");
}
a -= m;
}
if (fputs(crflag ? "\r\n" : "\n", stream)) {
return printf("error fputs\n");
}
if (fclose(stream)) {
return printf("error fclose\n");
}
stream = fopen("test.bin", "r");
if (stream == NULL) {
return printf("error fopen(r)\n");
}
char* line = NULL;
size_t capacity = 0;
ssize_t n = getline(&line, &capacity, stream);
int err = errno;
printf("cap:%12zu ssize_t:%12lld feof:%d ferror:%d errno:%2d line:%p %s ", //
capacity, (long long)n, feof(stream), ferror(stream), err, (void*)line, strerror(err));
free(line);
if (fclose(stream)) {
return printf("error fclose\n");
}
return printf("Fin\n");
}
int main() {
for (unsigned sh = 28; sh < 31; sh++) {
unsigned long long a = 1ull << sh;
djtest(sh, a, 0);
djtest(sh, a, 1);
fflush(stdout);
a *= 2;
}
printf("All done\n");
return 0;
}
Выход
sh:28 a: 268435456 crlf:0 cap: 536870912 ssize_t: 268435457 feof:0 ferror:0 errno: 0 line:0xbff20008 No error Fin
sh:28 a: 268435456 crlf:1 cap: 536870912 ssize_t: 268435458 feof:0 ferror:0 errno: 0 line:0xbff20008 No error Fin
sh:29 a: 536870912 crlf:0 cap: 1073741824 ssize_t: 536870913 feof:0 ferror:0 errno: 0 line:0x1ff80008 No error Fin
sh:29 a: 536870912 crlf:1 cap: 1073741824 ssize_t: 536870914 feof:0 ferror:0 errno: 0 line:0x1ff80008 No error Fin
sh:30 a: 1073741824 crlf:0 cap: 1073741824 ssize_t: 1610088455 feof:0 ferror:0 errno:12 line:0x1ff80008 Cannot allocate memory Fin
sh:30 a: 1073741824 crlf:1 cap: 1073741824 ssize_t: 1610088455 feof:0 ferror:0 errno:12 line:0x1ff80008 Cannot allocate memory Fin
All done
GNU C11 (GCC) версии 6.4.0
person
chux - Reinstate Monica
schedule
20.09.2017