Look at the expression getline(&line, &len, data)
and read the manpage:
If *line is set to NULL and *len is set 0 before the call, then
getline() will allocate a buffer for storing the line. This buffer
should be freed by the user program even if getline() failed.
This should be the case on your first time round the loop (although we can't see where len
is declared, let's just assume your real code does this correctly)
Alternatively, before calling getline(), *line can contain a
pointer to a malloc(3)-allocated buffer *len bytes in size. If the
buffer is not large enough to hold the line, getline() resizes it
with realloc(3), updating *line and *len as necessary.
OK, so if line != NULL
it must point to a buffer allocated by malloc
of size len
. The buffer allocated by your first call to getline
(as above) satisfies this.
Note it's not good enough for line
to point somewhere into that buffer, it must be the beginning.
Now look at the expression strsep(&line,"|")
and read the manpage for that:
... This token is terminated by overwriting the delimiter with a
null byte ('\0'), and *line is updated to point past the token
So, the first argument (line
) is changed so that you can call strsep
again with the same first argument, and get the next token. This means line
is no longer a valid argument to getline
, because it isn't the start of a malloc
'd buffer (and the length len
is also now wrong).
In practice, either
getline
will try to read len
bytes into the buffer you gave it, but since you advanced line
by the length of the first token, it writes off the end of your allocated block. This might just damage the heap rather than dying immediately
getline
will try to realloc the buffer you gave it, but since it isn't a valid allocated block, you get heap damage again.
While we're here, you also don't check p
is non-NULL, but damaging line
is the main problem.
Oh, and if you think the problem is allocation-related, try using valgrind
- it generally finds the moment things first go wrong.