patterncMinor
Read until EOF and realloc as needed
Viewed 0 times
neededuntilreadeofreallocand
Problem
This is a function that reads until
Do you have any improvement suggestions?
EOF and reallocs as it goes.char *
read_to_end(int fd, int *bread)
{
ssize_t size, nread, rc;
char *buf, *tmp;
nread = 0;
size = MINLEN;
buf = malloc(size);
while ((rc = read(fd, buf + nread, size - nread))) {
if (rc < 0) {
if (errno == EINTR)
continue;
goto error;
}
nread += rc;
/* See if we need to expand. */
if (size - nread < MINLEN) {
size *= 2;
/* Make sure realloc doesn't fail. */
if (!(tmp = realloc(buf, size)))
goto error;
buf = tmp;
}
}
/* Shrink if necessary. */
if (size != nread && !(tmp = realloc(buf, nread)))
goto error;
buf = tmp;
*bread = nread;
return buf;
error:
free(buf);
return NULL;
}Do you have any improvement suggestions?
Solution
Seeing this is 'unanswered' here's my tuppence worth:
If you are reading a file I suggest you get the file size first, eg using
Alternatively, if the file is big and you have OS support, consider mapping the file into memory using
On your code, I have a few comments:
-
If you have a stderr, perhaps add a call to
-
It looks as if you always re-alloc, even if the initial buffer is big enough.
-
If zero bytes are read, you will
-
Add a bracket around
-
I would prefer
If you are reading a file I suggest you get the file size first, eg using
fstat(), allocate a buffer of the correct size and read into that. Alternatively, if the file is big and you have OS support, consider mapping the file into memory using
mmap(). This maps the file into virtual memory but does not read it immediately. As you access the memory into which the file is mapped the file is read into that address space for you (in the background) by the OS.On your code, I have a few comments:
-
If you have a stderr, perhaps add a call to
perror() on error.-
It looks as if you always re-alloc, even if the initial buffer is big enough.
-
If zero bytes are read, you will
realloc(buf, 0). realloc man page says this is ok.-
Add a bracket around
size != nread - I always have to check operator precedence in statements like this and I guess I am not alone. Brackets save the reader the trouble.-
I would prefer
*bread to be set to 0 on failure. Should bread be size_t ?Context
StackExchange Code Review Q#9421, answer score: 3
Revisions (0)
No revisions yet.