On Fri, May 24, 2019 at 07:22:07PM +0700, Oleg Chumanov wrote: > First of all, I really want to thank you for your files. > > However, Can you show me an example of these: > > > makes it easier to perform error > > recovery in the caller. For example, the caller may wish to > > reallocate the buffer and retry. > > > > That would make it a bit harder to do error recovery since you'd > > need to compute the required length > > I mean, I can do something like this: > > offset = 0; > while ((n = olegcpy(buf + offset, str + offset, buf_size - offset))) { > offset = buf_size - 1; > buf_size += n; > buf = realloc(buf, buf_size); > }
Of course, you could, but you are totally missing the point of strlcpy/strlcat. Look, the basic idea is that developers make mistakes. All of them. Including *you*. Not all the time, but once is enough, especially where buffer overflows are concerned. Your proposed interface (which I renamed olegcpy) is more complex to use than regular strlcpy. Look, you *are* doing pointer arithmetic in your loop. Oh, btw, your code is wrong... you forgot to check that buf_size didn't overflow (unlikely, I know), and you *also* forgot to check that realloc did work. That's not your point ? Actually, it *is*. You had to devote brain cells to thinking about your very smart loop, so you missed a few trivial points. That's what strlcpy is all about. It's a PLAIN SIMPLE interface designed for ACTUAL PEOPLE. Compare that with strlcpy while (1) { size_t n = strlcpy(buf, str, buf_size); if (n < bufsize) break; char *newb = realloc(buf, n); if (!newb) { free(buf); /* oh hey, that's an error */ exit(1); } buf = newb; buf_size = n; } Oh, hey, I didn't forget to test for actual errors. Because the code is simpler. So, yes, I copy the same string twice, once in a blue moon. Guess what ? FOR REAL PROGRAMS IT DOESN'T MATTER. *IF* your buffer sizes are carefully chosen, you won't reallocate them THAT often (especially because the smart thing to do is to devote energy to actually track average buffer sizes and reuse buffers so you don't reallocate all the time). So, in reality, I won't ever realloc *exactly* what strlcpy gives me. My code looks more like this usually: while (1) { size_t n = strlcpy(buf, str, buf_size); if (n < bufsize) break; while (n > bufsize) bufsize <<= 1U; char *newb = realloc(buf, bufsize); if (!newb) { free(buf); /* oh hey, that's an error */ exit(1); } buf = newb; } and I do *love* strlcpy and strlcat because they're simple enough to use that I can spend my time concentrating on stuff that actually matters, without too much risk at introducing more bugs in existing programs. "Premature optimization is the root of all evil" (Don E. Knuth)