LWN.net Logo

Advertisement

Advanced thin client solution for Linux, based on Open Source. Mix Windows and Linux, 10 licenses for free!

Advertise here

snprintf() confusion

snprintf() confusion

Posted Feb 5, 2004 6:02 UTC (Thu) by IkeTo (subscriber, #2122)
Parent article: snprintf() confusion

I think the convention that sprintf returns the number of bytes written (rather than "would be written") does not make a real lot of sense: you never know whether your buffer is large enough, so there is no way to inform the user that something is truncated. And even if you guess it is not (because buffer size == return value), you have no way to allocate the required memory size. Given that most programmers won't even use snprintf, I think that educating those who are already better off should be easy: all they need is to use the min of the returned value and the buffer size if they want the scnprintf semantics.


(Log in to post comments)

snprintf() confusion

Posted Feb 5, 2004 8:43 UTC (Thu) by ThePythonicCow (subscriber, #11308) [Link]

Historically, there have been two variants of snprintf, with the ISO C99 standard, taken from BSD, of returning the length of the entire formatted string, even if it didn't entirely fit.

Earlier versions of snprintf only returned a count of how many non-nul characters went into the buffer.

This earlier return convention was actually "obvious" at the time -- no one on those slow, old machines would expect a C library routine to be wasting its CPU cycles calculating the length of some formatted output that it wasn't going to output.

And my impression is that most of us old timers are surprised by the new convention.

This new convention is also not worth much in most kernel code, which doesn't do anything with the extra information anyway. If the intended output doesn't fit (it's usually a console print or something) then tough - it gets truncated. Not usually worth the bother to try to expand the buffer size (and you have to be careful, not to open the kernel up to a Denial of Service attack, if the user can somehow persuade it to attempt to print something that's surprisingly long.

Still, Linus has clearly chosen the new ISO C99 standard (someone backed the lib/vsprintf.c code off to the "old standard", and Linus restored the C99 conventions.

snprintf() confusion

Posted Feb 6, 2004 23:50 UTC (Fri) by giraffedata (subscriber, #1954) [Link]

This earlier return convention was actually "obvious" at the time -- no one on those slow, old machines would expect a C library routine to be wasting its CPU cycles calculating the length of some formatted output that it wasn't going to output

I doubt the wasted computation entered into the decision. The reason the old behavior was obvious at the time is that the function is emulating printf(), which like all Unix I/O routines, returns the number of characters transferred.

The modern sprintf return value, though useful, is actually quite unconventional.

snprintf() confusion

Posted Feb 7, 2004 10:00 UTC (Sat) by ThePythonicCow (subscriber, #11308) [Link]

    I doubt the wasted computation entered into the decision.
Hmmmm ... I feel we are both guessing slightly off. You're likely right it wasn't an explicit decision to save cpu cycles. But the analogy with printf is fragile as well - it's not like printf has a choice of two possible lengths to choose from. It writes whatever it has format for, and counts it all (or SEGV's trying).

Your last words:

    is actually quite unconventional
might come closest to the mark. Something about the modern value just seems odd. The early snprintf creators perhaps didn't even consider that choice of return value as an alternative.

snprintf() confusion

Posted Feb 7, 2004 18:09 UTC (Sat) by giraffedata (subscriber, #1954) [Link]

it's not like printf has a choice of two possible lengths to choose from. It writes whatever it has format for, and counts it all (or SEGV's trying).

OK, I see in the printf case, a partial write isn't practical. But it doesn't really weaken the argument that printf is an I/O routine, and so it is natural to follow the pattern of write() and fwrite() and return the number of bytes written.

The leap from there to snprintf() is a lot more obvious when you include the sprintf() step. sprintf(), derived from printf(), quite naturally returns the number of characters formatted, just like printf(). And it's a very useful value, too. snprintf() was derived from sprintf(), and merely adds a constraint on the length; If you're going to drop it in to replace a dangerous sprintf(), you clearly want it to do the same as sprintf() and return the number of characters formatted.

snprintf() confusion

Posted Feb 7, 2004 18:56 UTC (Sat) by ThePythonicCow (subscriber, #11308) [Link]

Yeah - that makes sense.

Copyright © 2008, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds