COLLECTED BY
Organization:
Alexa Crawls
Starting in 1996,
Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to the
Wayback Machine after an embargo period.
Starting in 1996,
Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to the
Wayback Machine after an embargo period.
The Wayback Machine - https://web.archive.org/web/20160229080205/http://udel.edu:80/~pconrad/UnixAtUD/strcpy.html
A rant about strcpy, strncpy and strlcpy.
Here's a little rant about strcpy, strncpy and strlcpy.
(You'll note that I cite a variety of sources including Microsoft,
Unix and Apple documentation, so this is a very ecumenical
discussion. :-) )
I teach that strcpy is dangerous, and should avoided in favor
of strncpy.
The following article from the Microsoft Developer's Network (MSDN) is very
harshly critical of this teaching, so I recommend this article to
you for your
consideration and critical analysis.
link to MSDN article mentioning strcpy vs strncpy
Funny, I think the MSDN author's line of argument actually just
supports my point rather than refutes it, since strcpy is an example
of the kind of code he claims should not be written (a loop bounded by
reaching a \0 rather than by a counter.)
Of course, the cure (strncpy) can be as bad as the disease; maybe that's
the MSDN author's point. I appreciate his point that strcpy can be
used safely in LIMITED circumstances, and strncpy can be unsafe if you
aren't careful.
For example, a key problem with strncpy is that if the length of the
src string is >= n, you end up without null termination. I usually
do the following for safety:
char dest[LEN];
char *src;
... /* src is set to point to a source string of unknown length */
strncpy(dest,src,LEN);
dest[LEN-1]='\0'; /* null terminate for safety */
Maybe code without that extra null termination is an example
of code that uses strncpy but is nevertheless dangerous.
The assignment of dest[LEN-1] to \0 is redundant and harmless
if the string is already NULL terminated, and vital if strlen(src) >= LEN.
I'm assuming that a one byte copy is cheap enought that it isn't worth
the cycles or the code clutter to do an if test to check whether the
assignment is strictly necessary (e.g. if strlen(src) >= LEN).
In each lecture where I've taught this, one of the more clever students
has asked (both in 105 and 181) something to the effect of "why doesn't
strncpy just do that NULL terminating thing for you"?
I've replied: "Are you suggesting, in so many words, that strncpy's
behavior is kind of dumb?" They say, "yeah". I say "Well, I agree
with you, and apparently someone else did too, because someone came
along and wrote a function called strlcpy, that does something more
like what we might expect strncpy to do. See:
"man strlcpy" on strauss
http://www.daemon-systems.org/man/strlcpy.3.html
But since strlcpy came along later, it is not as widely-implemented
or widely known. Lots of textbooks don't talk about it, and some systems
don't implement it yet. So you need to know about strncpy.
Note, for example, what the Apple documentation for strcpy/strncpy says about
strlcpy; namely, that it is "not defined in any standards" and "should only be
used when portability is not a concern."
link to strcpy page in Apple developer docs
The Apple page for strlcpy
also has some interesting information on the topic:
link to strlcpy page in Apple developer docs
Here's a question for reflection. My proposed way of copying a string is:
char dest[LEN];
char *src;
... /* src is set to point to a source string of unknown length */
strncpy(dest,src,LEN);
dest[LEN-1]='\0'; /* null terminate for safety */
Sometimes a student will suggest "why not just copy one fewer characters;
doesn't that fix things so that you don't need the extra line to do
the NULL terminating?"
For example:
char dest[LEN];
char *src;
... /* src is set to point to a source string of unknown length */
strncpy(dest,src,LEN-1);
My reply is that this doesn't work. Can you explain why it doesn't?
Under what circumstances does this fail to result in a null-terminated
destination string?
Final Thoughts
- I stand by my claim that strcpy should be generally be avoided in favor of strncpy. (Note that "generally avoid" doesn't mean "never use"; it does mean don't use without CAREFULLY considering the circumstances.)
- Using strncpy is helpful, but is not, in and of itself, a guarantee of safety. You still have to be careful about NULL termination issues when the src string is longer than, or equal in length to, the destination string.
- Use strlcpy if you can get away with it, but be careful of portability. I'll still teach strncpy unless and until I can be convinced that strlcpy is so ubiquitious that strncpy is considered obsolete.
Phillip T Conrad
Last modified: Tue Nov 30 14:56:06 EST 2004