Why should I use my own buffer for getline or similar functions?
I was writing a program the other day when I was using a function getline()
and I realized something that I never thought of and could not find anything about it on the internet.
As described getline
on the man page:
DESCRIPTION
The function
getdelim()
reads a string from the stream, delimited by a character separator. The function isgetline()
equivalent togetdelim()
the newline character as a separator. The delimiter character is included as part of the line if the end of the file is not reached.The caller can supply a pointer to the malloced buffer for line at
*linep
and the capacity of that buffer at*linecapp
. These functions expand the buffer as needed, as if throughrealloc()
. Iflinep
points to a pointerNULL
, a new buffer will be allocated. In any case,*linep
and*linecapp
will be updated accordingly.
Usually when I use this function, I always malloc my own buffer and pass it to the getline funline pipe, but after reading this I realized that this is not necessary since it will only be created.
My question is, is there a reason why I should create my own buffer and then pass it to getline and not just pass NULL
and let getline process the buffer?
The only reason I could think of is if you want to control the size of the buffer, but that doesn't seem right because it says it will resize the buffer as needed.
When should I use my own buffer, and when should I let getline handle the creation of the buffer?
source to share
Q: Is there a reason why I should create my own buffer and then pass it to getline and not just pass NULL and let getline handle the buffer?
A: Generally not. In some situations, it makes sense to highlight the selection before calling getline()
.
1) Many redistribution schemes getline()
are liner. That is, it will allocate a buffer of N bytes (e.g. 256, 1k, 4k). Then if that isn't enough, try 2 * N, 3 * N, 4 * N, 5 * N, etc. If for some reason the code expects regular large buffer needs, allocating one large buffer before calling will getline()
prevent the getline()
small buffers from being moved again. Potential, if questionable, efficiency gains.
size_t size = 10000;
char *buf = mallc(size);
ssize_t numchar = getline(&buf, &size, ...);
2) If the code is needed or has a working buffer available before the call getline()
, it's ok to use.
size_t size = 100;
char *buf = mallc(size);
...
foo(buf, size);
...
// No need for these steps
// free(buf);
// size = 0;
// buf = NULL;
...
ssize_t numchar = getline(&buf, &size, ...);
...
free(buf);
3) Repeated calls. This includes a loop in which calls are repeated getline()
. No need to free in the loop, wait for the loop to complete. @Alan Stokes
// do not use this
while (some_condition) {
size_t size = 0;
char *buf = NULL;
ssize_t numchar = getline(&buf, &size, ...);
foo(numchar, buf,size);
free(buf);
}
// instead, use this model
size_t size = 0;
char *buf = NULL;
while (some_condition) {
ssize_t numchar = getline(&buf, &size, ...);
foo(numchar, buf,size);
}
free(buf);
Q2: When should I use my own buffer, and when should I let getline handle creating the buffer?
A2: Allocate your own buffer when the code certainly needs or benefits from it. Else let getline()
do it.
source to share
-
No reason, the buffer is needed
realloc
d as needed and you needfree
it yourself. So you can just passNULL
to make sure it gets throughlength == 0
. -
I don't see a situation where it would be good to use your own dedicated buffer, you would still use
malloc
and what to usegetline
getdelim
.
Of course, if you pass a large enough buffer, you would disallow calling realloc
on each getline
, but you can test with valgrind
, and for most common cases there will be as few calls as possible realloc
.
source to share