On 2010-11-11, Lawrence D'Oliveiro <l...@geek-central.gen.new_zealand> wrote:
> Another function that should be deprecated is strncat???I myself was caught
> out misunderstanding it recently. What purpose does it serve?
I'm wondering if you're thinking of strncpy(), which is the famously bogus
one. strncat() just has a fencepost error -- given a limit N, it will
write at most N+1 characters. strncpy(), however, pads with null bytes
if the source string isn't long enough, and does not null terminate if there
isn't room to.
This behavior is nearly always undesireable. However, if you were building
a filesystem in which file path names were given exactly sixteen bytes of
space in the directory entry, and you didn't want to truncate them to 15
bytes, you might write precisely this behavior. So that's what we got.
I don't know whether anyone's gotten buy-in from the standards people
for strlcpy()/strlcat(), but I really hope so. Me, I just use
snprintf with a %s format instead of str*cpy().
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
Like strtok, it serves a niche purpose that doesn't come up as
often as people might think.
Seebs <usenet-nos...@seebs.net> wrote:
> I'm wondering if you're thinking of strncpy(),
> which is the famously bogus one.
Yet it's actually strncat that is the odd one out of the trio...
strncat(p, q, n) - p is string, q is array
strncmp(p, q, n) - p is array, q is array
strncpy(p, q, n) - p is array, q is array
If they were prefixed memn, instead of strn, then I'm reasonably
sure there would be fewer complaints and surprises with strncpy.
The problem with strncpy is not that it pads with zero or won't
terminate a full array. The problem is that it doesn't let you
choose the pad character.
--
Peter
> The problem with strncpy is not that it pads with zero or won't
> terminate a full array. The problem is that it doesn't let you
> choose the pad character.
It's not really strncpy's fault, but in my experience the biggest
problems with strncpy are that people don't understand what it
does. Some people expect it to always null-terminate; other
people don't realize that how expensive it is to copy a short
string into a large buffer with strncpy(). (I once made a
program much faster by using a function other than strncpy() to
copy a usually short file name into a 4096-byte buffer.)
--
Ben Pfaff
http://benpfaff.org
> (Note followups, this has stopped being very Pythony.)
>
> On 2010-11-11, Lawrence D'Oliveiro <l...@geek-central.gen.new_zealand>
> wrote:
>
>> Another function that should be deprecated is strncat???I myself was
>> caught out misunderstanding it recently. What purpose does it serve?
>
> I'm wondering if you're thinking of strncpy(), which is the famously bogus
> one.
I don’t see what’s bogus about that. From my Linux man page:
char *strncpy(char *dest, const char *src, size_t n);
The strncpy() function is similar, except that at most n bytes of
src are copied. Warning: If there is no null byte among the first n
bytes of src, the string placed in dest will not be null-terminated.
That seems straightforward enough: n is the size of dest. The problem with
strncat is that the size limit controls how much of the _source_ string will
be copied, it says nothing about the maximum size of the _destination_
buffer. To me, that makes no sense.
Of course, it goes without saying that strcat and strcpy should be encased
in concrete overshoes and dropped off a pier somewhere...
> I don't know whether anyone's gotten buy-in from the standards people
> for strlcpy()/strlcat(), but I really hope so.
They do seem like much more sensible functions. Though personally I would
rather do away with null-terminated strings.
> Me, I just use snprintf with a %s format instead of str*cpy().
That’s an idea I should think about. :)
> I don’t see what’s bogus about that. From my Linux man page:
>
> char *strncpy(char *dest, const char *src, size_t n);
>
> The strncpy() function is similar, except that at most n bytes of
> src are copied. Warning: If there is no null byte among the first n
> bytes of src, the string placed in dest will not be null-terminated.
>
> That seems straightforward enough: n is the size of dest.
You snipped the bizarre bit:
If the length of src is less than n, strncpy() pads the remainder
of dest with null bytes.
Basically, it means `fill this here buffer with string stuff from there,
padding with zeroes if there wasn't enough string'. It's what you
wanted for filling in tar headers and suchlike, but not for writing safe
string handling.
> > I don't know whether anyone's gotten buy-in from the standards people
> > for strlcpy()/strlcat(), but I really hope so.
>
> They do seem like much more sensible functions. Though personally I
> would rather do away with null-terminated strings.
That's trickier because they're part of the language proper (string
literals are null terminated and include the terminator in their sizes)
and wired throughout too many operating system interfaces.
> > Me, I just use snprintf with a %s format instead of str*cpy().
>
> That’s an idea I should think about. :)
I use a simple dynamic string library for more or less everything. It
doesn't try to do everything, but it does do simple concatenation and
formatting, and it /doesn't/ prevent you getting at the underlying
characters if there's something it missed.
-- [mdw]
> I don???t see what???s bogus about that.
The combination of padding and possibly not null-terminating.
> That seems straightforward enough: n is the size of dest. The problem with
> strncat is that the size limit controls how much of the _source_ string will
> be copied, it says nothing about the maximum size of the _destination_
> buffer. To me, that makes no sense.
Wow. You know, I'd never thought about that. I always did it by using
information about the destination to pick n, but that's just evidence that
it's so broken I've always had to work around it. :)
> They do seem like much more sensible functions. Though personally I would
> rather do away with null-terminated strings.
In higher level languages, sure. In C, they have a lot of advantages that
have made them a useful format. Mostly.
> This behavior is nearly always undesireable. However, if you were building
> a filesystem in which file path names were given exactly sixteen bytes of
> space in the directory entry, and you didn't want to truncate them to 15
> bytes, you might write precisely this behavior.
Well, 14 actually, not 16. The last two bytes were for the inode number.
Agh. I even knew that, and then I thought "no, I'm sure there was a 16
in there somewhere".
... And yes, I'm this bad at pretty much everything to do with remembering
details. I have learned to live my life in terms of reference materials.