A test harness that shows the problem.
A difference between this code and OP's is that the status of errno
is always shown.
When out-of-memory occurs, errno
is set, but getline()
returned the length exceeding the capacity
- very strange - and not -1.
If this is compliant or not, I leave to your interpretation of the below. IMO it is not compliant. I would expect a return value of -1, if errno
is set due to getline()
for any reason in addition to ferror()
or no read on end-of-file.
I suspect the issue due to a deferred memory allocation.
RETURN VALUE
On success, getline()
and getdelim()
return the number of characters read, including the delimiter character, but not including the terminating null byte ('\0'). This value can be used to handle embedded null bytes in the line read.
Both functions return -1 on failure to read a line (including end-of-file condition). In the event of an error, errno is set to indicate the cause.
ERRORS
EINVAL Bad arguments (n or lineptr is NULL, or stream is not valid).
ENOMEM Allocation or reallocation of the line buffer failed.
Code also experiments with CR/LF vs LF, yet that did not appear relevant.
#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;
}
Output
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) version 6.4.0