From: Alf P. Steinbach on
* Greg Herlihy:
> On Jul 5, 11:21 am, red floyd <no.spam.h...(a)example.com> wrote:
>>
>> Greg Herlihy wrote:
>>> For one, strncpy() has no parameter specifying the size of the
>>> destination buffer
>> char *strncpy(char *s1, const char *s2, size_t n);
>>
>> What is that third paramerer, then?
>
> The third parameter to strncpy() specifies the maximum number of
> characters that the function is to copy from s2 to s1 - a number which
> could be larger, smaller or the same - as the number of bytes in the
> destination buffer. After all, the number of bytes allocated for the
> destination buffer, s1, is not a function of strncpy()'s third
> parameter, "n". Therefore, the only way for strncpy() to know the size
> of the destination buffer is for the caller to provide that
> information with an additional parameter.
>
> Moreover, it is easy enough to demonstrate this non-correlation with
> some examples of strncpy() calls. Because - if there is some kind of
> correlation between "n" and the size of the s1 buffer _ then changing
> the size of the destination buffer should also affect the value of n.
> For example, calling strncpy() to copy (at most) two characters of a
> string into a 16-byte buffer should pass a different "n" then a
> strncpy() call to copy (at most) two characters into a 32-byte buffer.
> Yet, the value of "n" is the same for both calls:
>
> char bufA[16]; bufB[32];
>
> stncpy(bufA, "one", 2);
> stncpy(bufB, "one", 2); // destination buffer size has changed -
> // but the value of "n" has not
>
> whereas the comparable call to strncpy_s() does show the expected
> change (in the value of second argument) whenever the size of the
> destination buffer, s1, changes :
>
> strncpy_s(bufA, sizeof(bufA), "one", 2);
> strncpy_s(bufB, sizeof(bufB), "one", 2); // value of second
> argument changes

One may just as well use sizeof() (properly) in the strncpy calls, and a literal
also for buffer size in the strncpy_s calls, which according to the above
reasoning would then provide the opposite conclusion, which means that the above
reasoning is invalid. It is invalid because it's circular. It is circular
because it assumes that only the shown usage is correct, then it argues from
that that only the shown usage is correct.

However, in spite of this invalid circular reasoning there /is/ a behavioral
difference: an invalid inference's conclusion might be true! ;-)

Namely, at least according to MSDN documentation, if strncpy_s determines that
the destination buffer is too small for the specified number of characters to
copy, then the destination string is simply set to "".


> Therefore - and exactly as I noted in my previous post - there is no
> way for a caller to provide (nor anyway for strncpy() to deduce on its
> own) the size of the destination buffer.

The "no way to provide" is incorrect. Not sure what's meant by the last part,
"no way to deduce on its own". But at least with Microsoft's implementation, one
advantage of strncpy_s is precisely that at the C++ level (this obviously does
not apply to the C draft standard...) it /can/ infer buffer size on its own.


Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Greg Herlihy on
On Jul 6, 3:33 pm, "Alf P. Steinbach" <al...(a)start.no> wrote:
> * Greg Herlihy:
>
>> > The third parameter to strncpy() specifies the maximum number of
> > characters that the function is to copy from s2 to s1 - a number which
> > could be larger, smaller or the same - as the number of bytes in the
> > destination buffer. After all, the number of bytes allocated for the
> > destination buffer, s1, is not a function of strncpy()'s third
> > parameter, "n". Therefore, the only way for strncpy() to know the size
> > of the destination buffer is for the caller to provide that
> > information with an additional parameter.
>
> > Moreover, it is easy enough to demonstrate this non-correlation with
> > some examples of strncpy() calls. Because - if there is some kind of
> > correlation between "n" and the size of the s1 buffer _ then changing
> > the size of the destination buffer should also affect the value of n.
> > For example, calling strncpy() to copy (at most) two characters of a
> > string into a 16-byte buffer should pass a different "n" then a
> > strncpy() call to copy (at most) two characters into a 32-byte buffer.
> > Yet, the value of "n" is the same for both calls:
>
> > char bufA[16]; bufB[32];
>
> > stncpy(bufA, "one", 2);
> > stncpy(bufB, "one", 2); // destination buffer size has changed -
> > // but the value of "n" has not
>
> > whereas the comparable call to strncpy_s() does show the expected
> > change (in the value of second argument) whenever the size of the
> > destination buffer, s1, changes :
>
> > strncpy_s(bufA, sizeof(bufA), "one", 2);
> > strncpy_s(bufB, sizeof(bufB), "one", 2); // value of second
> > argument changes
>
> One may just as well use sizeof() (properly) in the strncpy calls, and a literal
> also for buffer size in the strncpy_s calls, which according to the above
> reasoning would then provide the opposite conclusion, which means that the above
> reasoning is invalid.

Not at all. A function call can be considered "correct" if it produces
the results as expected. So, there is nothing that rules out passing
sizeof(s1) as a (correct) third argument to strncpy(). For that
matter, there is nothing that prevents other values from being correct
as well: such as a favorite number, or the number of C++ books read in
the last month. or the number of lines in the current source file -
any of these values can be just as valid as sizeof(s1) - provided that
the value of whatever the programmer does decide to pass (as
strncpy()'s third argument) - is equal to the maximum number of
characters to be copied from s2 to s1.

In other words, the third argument to strncpy() always specifies the
maximum number of characters to copy - no matter what other
(equivalent) value (specifically, in this example, the size of the
destination buffer) that the programmer might have contrived to pass
as an replacement of equal value..

> > Therefore - and exactly as I noted in my previous post - there is no
> > way for a caller to provide (nor anyway for strncpy() to deduce on its
> > own) the size of the destination buffer.
>
> The "no way to provide" is incorrect. Not sure what's meant by the last part,
> "no way to deduce on its own". But at least with Microsoft's implementation, one
> advantage of strncpy_s is precisely that at the C++ level (this obviously does
> not apply to the C draft standard...) it /can/ infer buffer size on its own.

strncpy_s() does not deduce the size of the destinationn buffer on its
own. Instead the caller explicitly specifies (in the second argument)
the size of the desintation buffer.

It is not possible to "provide" information to a function - that the
function is not expecting. After all, if I call strncpy() and pass my
age as the value of "n" (because my age happens to equal the maximum
number of characters to copy from s1 to s1), would that mean that it
is possible for a C++ programmer to "provide" their age to strncpy()?
And, if not, then why would providing the (equally unexpected) size of
the destinatino buffer, be any different?

Greg


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Eberhard Schefold on
Greg Herlihy wrote:

> On Jul 6, 3:33 pm, "Alf P. Steinbach" <al...(a)start.no> wrote:

>> The "no way to provide" is incorrect. Not sure what's meant by the last part,
>> "no way to deduce on its own". But at least with Microsoft's implementation, one
>> advantage of strncpy_s is precisely that at the C++ level (this obviously does
>> not apply to the C draft standard...) it /can/ infer buffer size on its own.
>
> strncpy_s() does not deduce the size of the destinationn buffer on its
> own. Instead the caller explicitly specifies (in the second argument)
> the size of the desintation buffer.

This is the signature that Alf is probably referring to:

template< size_t size > errno_t strcpy_s(
char ( &strDestination )[ size ],
const char * strSource
);

If the target buffer is declared as an array sized at compile time, the
template can deduce the size, and the third parameter becomes
unnecessary. In this case, the migration from existing code is very
easy; you just add "_s".

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Maxim Yegorushkin on
On Jul 2, 6:58 pm, Thomas Richter <t...(a)math.tu-berlin.de> wrote:
> Trups schrieb:
>
> > I have changed my strcpy to strcpy_s for 2005 project. It's fairly
> > big project and was using strycpy lot of places.
> > The program started corrupting the stack and in turn crashing the
> > application. We have realized that it is due to strcpy_s. We have
> > changes that to strpcy and then it was fine.
>
> First, strcpy_s is a microsoftism. Don't use it for portable programs.
> Instead, either ensure that your destination buffer is sufficient, or
> use strncpy().

strncpy() is not a good idea either. The long story is here:
http://blogs.msdn.com/oldnewthing/archive/2005/01/07/348437.aspx

Better use "strlcpy and strlcat - consistent, safe, string copy and
concatenation" from http://www.gratisoft.us/todd/papers/strlcpy.html

Max


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alf P. Steinbach on
* Greg Herlihy:
>
> In other words, the third argument to strncpy() always specifies the
> maximum number of characters to copy - no matter what other
> (equivalent) value (specifically, in this example, the size of the
> destination buffer) that the programmer might have contrived to pass
> as an replacement of equal value..

No disagreement about the first part of that long sentence, but the rest
just
baffles me. Anyway, doesn't seem to be relevant to previous discussion.


>>> Therefore - and exactly as I noted in my previous post - there is no
>>> way for a caller to provide (nor anyway for strncpy() to deduce on its
>>> own) the size of the destination buffer.
>> The "no way to provide" is incorrect. Not sure what's meant by the last
part,
>> "no way to deduce on its own". But at least with Microsoft's
implementation, one
>> advantage of strncpy_s is precisely that at the C++ level (this obviously
does
>> not apply to the C draft standard...) it /can/ infer buffer size on its
own.
>
> strncpy_s() does not deduce the size of the destinationn buffer on its
> own. Instead the caller explicitly specifies (in the second argument)
> the size of the desintation buffer.

Perhaps you're not aware that strncpy_s, at the C++ level (keep in mind that

then we are, at this point in time, talking about an MS extension, even
though
the C part is heading towards adoption in non-MS world), is an overloaded
function, and that that overloading is crucial for its intended safety
purpose?

It shouldn't really be a point of contention. After all, it means that
strncpy_s
is a bit different. Which was the point that you, as I understood it, was
trying
to make in an earlier article in this thread.

Let me therefore most humbly and courteously just direct you /again/ to the
documentation[1]. Or as we said in the old days, RTFM. And if you do, then I

think you'll discover that indeed strncpy_s does deduce the size of the
destination buffer on its own, when that's possible, contrary to stated
above.


> It is not possible to "provide" information to a function - that the
> function is not expecting. After all, if I call strncpy() and pass my
> age as the value of "n" (because my age happens to equal the maximum
> number of characters to copy from s1 to s1), would that mean that it
> is possible for a C++ programmer to "provide" their age to strncpy()?
> And, if not, then why would providing the (equally unexpected) size of
> the destinatino buffer, be any different?

It seems the immediately above paragraph is inadvertently quoting from some
other newsgroup, and perhaps responding to some unspecified article in some
other newsgroup? Anyway, yes, we can let 42 stand for anything, but so what?
I'm
sorry but it's not meaningful to me.


Cheers, & hth.,

- Alf


Notes:
[1] Typing "msdn strncpy_s" in the Firefox address bar works fine for me.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]