Reputation: 11770
I'm trying to add getline
support to http-fs-wrapper and I have some malloc problems.
ssize_t _intercept_getdelim(int fd, char **lineptr, size_t *n, int delim)
{
intercept_t *obj = intercept[fd];
int counter;
size_t nc = sizeof(char);
counter = -1;
while (obj->offset < obj->size)
{
++counter;
if (*lineptr) {
*lineptr = realloc(*lineptr, (counter + 2) * nc);
}
else {
*lineptr = malloc(nc);
}
_intercept_read(fd, lineptr[counter], nc);
if (*lineptr[counter] == delim)
{
break;
}
}
*n = counter ? counter + 1 : counter;
*lineptr[counter + 2] = '\0';
// Why do we need a *n when the return value is the same??
return *n;
}
Here's the relevant section of _intercept_read
:
size_t _intercept_read(int fd, void *buf, size_t count)
{
memcpy(buf, obj->ra_buf+bo, count);
When I step through this in gdb, the second iteration throws a SIGSEGV (from memcpy -- it's not the ending \0
, it's still inside the loop). I also don't quite get what's the difference between the *n
of getline
/getdelim
and the return value.
Upvotes: 1
Views: 798
Reputation: 11770
This works:
ssize_t _intercept_getdelim(int fd, char **lineptr, size_t *n, int delim)
{
intercept_t *obj = intercept[fd];
int counter = -1;
char *c, *newbuf;
*n = 1;
*lineptr = malloc(*n);
while (obj->offset < obj->size)
{
++counter;
if (counter >= *n)
{
if ((newbuf = realloc(*lineptr, *n << 1)))
{
*n = *n << 1;
*lineptr = newbuf;
}
else
{
return -1;
}
}
c = *lineptr + counter;
_intercept_read(fd, c, nc);
if (*c == delim)
{
break;
}
}
if (counter > -1)
{
*(*lineptr + ++counter) = '\0';
}
return counter;
}
Upvotes: 0
Reputation: 629
The difference between n and the return value is that n is always the buffer size, but the return value can be -1 for error states per posix spec. You aren't fully handling EOF (it should return -1 if it hits EOF and hasn't read anything yet).
A note, reallocing for every character is fairly inefficient. The standard pattern is to double the buffer size each time it is necessary. This is another way the return value and n can differ, since n is the buffer size, which can be much larger than the read character count it returns.
You also don't need to special case a starting null pointer, realloc internally calls malloc in that case.
buf = realloc(buf...) is an unsafe pattern, realloc can return null, you have to save the realloc result to a temp variable and check it before assigning, otherwise you both leak memory and can reference a null pointer.
I don't think there's actually space for the trailing null you're adding to the buffer at the end there.
Upvotes: 1