Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > strcpy implementation

Reply
Thread Tools

strcpy implementation

 
 
iC and iC++
Guest
Posts: n/a
 
      06-02-2010
I found this code in a very old book about pointers and I started
playing with it and I have a question.


#include <stdio.h>
#include <string.h>

main()
{
char x[5];
strcpy(x, "COMPILER");

printf("%s, %u, %d, \n", x, &x, sizeof(x));

getchar();
}

How deos strcpy assign all the characters in the code if x is only
defines as a 5 byte array? In other words, where are the extra bytes
stored and how is memory for them allocated. I looked at it while
debugging and there were no clues there.

thanks

 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      06-02-2010
"iC and iC++" <(E-Mail Removed)> writes:

> I found this code in a very old book about pointers and I started
> playing with it and I have a question.


What's its name?

> #include <stdio.h>
> #include <string.h>
>
> main()


int main(void) is better.

> {
> char x[5];
> strcpy(x, "COMPILER");


See below for my comments on this.

> printf("%s, %u, %d, \n", x, &x, sizeof(x));


Only one of the formats (%s) matches the type of supplied argument and
even that one (because of the strcpy error) won't necessarily print
correctly. What does the book claim is being illustrated here?

> getchar();


There should be a return statement here.

> }
>
> How deos strcpy assign all the characters in the code if x is only
> defines as a 5 byte array? In other words, where are the extra bytes
> stored and how is memory for them allocated. I looked at it while
> debugging and there were no clues there.


There are two ways to look at this. You can work out what happens on
one particular machine when the code is compiled with one particular
compiler and linked with one particular library; or you can look at it
is an incorrect program whose behaviour is not specified by the language
it appears to be written in.

The first can be useful but I don't think it will be in this case. The
second makes you focus on what constructs have well-defined meanings and
that is usually more productive. Here the lesson is that strcpy must
always have somewhere to cpy the str to.

--
Ben.
 
Reply With Quote
 
 
 
 
iC and iC++
Guest
Posts: n/a
 
      06-02-2010
On Jun 2, 6:44*pm, Richard Heathfield <(E-Mail Removed)> wrote:
> iC and iC++ wrote:
> > I found this code in a very old book about pointers and I started
> > playing with it and I have a question.

>
> > #include <stdio.h>
> > #include <string.h>

>
> > main()
> > * *{
> > * *char x[5];
> > * *strcpy(x, "COMPILER");

>
> > * *printf("%s, %u, %d, \n", x, &x, sizeof(x));

>
> > * *getchar();
> > }

>
> > *How deos strcpy assign all the characters in the code if x is only
> > defines as a 5 byte array?

>
> It can't (legally). If you don't provide enough storage in the target
> string to keep a copy of the source string, the behaviour of your
> program is undefined. In other words, by failing to provide sufficient
> storage you are breaking the contract between yourself and the
> implementation, and the implementation is therefore free to break the
> contract itself in any way it pleases.
>
> > In other words, where are the extra bytes
> > stored and how is memory for them allocated. I looked at it while
> > debugging and there were no clues there.

>
> A debugger can't teach you the rules of the language! There are no extra
> bytes (in the abstract machine) - in practice, strcpy just starts
> writing at x[0] and keeps going until it gets to a null character, so
> any data stored immediately after x[4] are going to get trashed.
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line vacant - apply within


Thats what I thought too, but it actually returns "COMPILER". That
definitely more characters than it has been allocated. Why isn't there
an error when there should be one. I am just curious.
 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      06-02-2010

"iC and iC++" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>I found this code in a very old book about pointers and I started
> playing with it and I have a question.
>
>
> #include <stdio.h>
> #include <string.h>
>
> main()
> {
> char x[5];
> strcpy(x, "COMPILER");
>
> printf("%s, %u, %d, \n", x, &x, sizeof(x));
>
> getchar();
> }
>
> How deos strcpy assign all the characters in the code if x is only
> defines as a 5 byte array? In other words, where are the extra bytes
> stored and how is memory for them allocated. I looked at it while
> debugging and there were no clues there.


It's undefined behavior. There is no defined behavior for undefined
behavior. A possible outcome would be to keep writing until it either
overwrote some other variables or intruded upon storage for which it had no
permission to access, triggering some sort of system response.

I would recommend not using that book.



Brian


 
Reply With Quote
 
iC and iC++
Guest
Posts: n/a
 
      06-02-2010
On Jun 2, 6:44*pm, Ben Bacarisse <(E-Mail Removed)> wrote:
> "iC and iC++" <(E-Mail Removed)> writes:
>
> > I found this code in a very old book about pointers and I started
> > playing with it and I have a question.

>
> What's its name?
>
> > #include <stdio.h>
> > #include <string.h>

>
> > main()

>
> int main(void) is better.
>
> > * *{
> > * *char x[5];
> > * *strcpy(x, "COMPILER");

>
> See below for my comments on this.
>
> > * *printf("%s, %u, %d, \n", x, &x, sizeof(x));

>
> Only one of the formats (%s) matches the type of supplied argument and
> even that one (because of the strcpy error) won't necessarily print
> correctly. *What does the book claim is being illustrated here?
>
> > * *getchar();

>
> There should be a return statement here.
>
> > }

>
> > *How deos strcpy assign all the characters in the code if x is only
> > defines as a 5 byte array? In other words, where are the extra bytes
> > stored and how is memory for them allocated. I looked at it while
> > debugging and there were no clues there.

>
> There are two ways to look at this. *You can work out what happens on
> one particular machine when the code is compiled with one particular
> compiler and linked with one particular library; or you can look at it
> is an incorrect program whose behaviour is not specified by the language
> it appears to be written in.
>
> The first can be useful but I don't think it will be in this case. *The
> second makes you focus on what constructs have well-defined meanings and
> that is usually more productive. *Here the lesson is that strcpy must
> always have somewhere to cpy the str to.
>
> --
> Ben.


The point this book is trying to make is as follows:
..."x does not equal "COMPILER". It only returns the memory address
at which the first character in the array is stored. Function that
accept this pointer are programmed to be "smart" and know to quit when
what they are doing after reading the NULL character."

So, even though, x only contains the first 5 bytes, the next 3 are
copied and when printf prints x, it continues past the 5th bit and
does not stop until the NULL is reached, as in this case.
 
Reply With Quote
 
bart.c
Guest
Posts: n/a
 
      06-02-2010
iC and iC++ wrote:
> On Jun 2, 6:44 pm, Richard Heathfield <(E-Mail Removed)> wrote:
>> iC and iC++ wrote:


>>> char x[5];
>>> strcpy(x, "COMPILER");

>>
>>> printf("%s, %u, %d, \n", x, &x, sizeof(x));


>>> How deos strcpy assign all the characters in the code if x is only
>>> defines as a 5 byte array?

>>
>> It can't (legally). If you don't provide enough storage in the target


> Thats what I thought too, but it actually returns "COMPILER". That
> definitely more characters than it has been allocated. Why isn't there
> an error when there should be one. I am just curious.


It works by chance. Whatever is being overwritten with the extra 4 bytes,
hasn't caused a crash or malfunction in this case (although you might want
to check the files on your hard drive are all still there..)

(Try a much longer string than "compiler". And/or a different compiler.)

C doesn't provide these safeguards except perhaps in certain
implementations.

--
Bartc

 
Reply With Quote
 
iC and iC++
Guest
Posts: n/a
 
      06-02-2010
On Jun 2, 7:07*pm, Richard Heathfield <(E-Mail Removed)> wrote:
> iC and iC++ wrote:
> > On Jun 2, 6:44 pm, Richard Heathfield <(E-Mail Removed)> wrote:
> >> iC and iC++ wrote:

>
> <snip>
>
> >>> * *char x[5];
> >>> * *strcpy(x, "COMPILER");
> >>> * *printf("%s, %u, %d, \n", x, &x, sizeof(x));
> >>> * *getchar();
> >>> }
> >>> *How deos strcpy assign all the characters in the code if x is only
> >>> defines as a 5 byte array?

>
> <snip>
>
> >> [...] in practice, strcpy just starts
> >> writing at x[0] and keeps going until it gets to a null character, so
> >> any data stored immediately after x[4] are going to get trashed.

>
> > Thats what I thought too, but it actually returns "COMPILER".

>
> When you break the rules, anything can happen, including what you
> observed to happen (but that isn't the only thing that could have happened).
>
> > That
> > definitely more characters than it has been allocated. Why isn't there
> > an error when there should be one. I am just curious.

>
> There *is* an error. The error is in the code. But this isn't the kind
> of error a compiler can catch (in the general case). It's what we know
> in the trade as a "bug".
>
> Let's just play pretend for a moment. Let's pretend that memory is laid
> out like this:
>
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> | * * | * * | * * | * * | * * | * * | * * | * * | * * |
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> <-- 5 bytes reserved for x --> <-- 4 bytes reserved
> * * * * * * * * * * * * * * * * * * for system time -->
>
> (In practice, no system would be daft enough to keep its timestamp so
> close to user memory, but we're just pretending.)
>
> First, let's take a look at our system time:
>
> *) TIME
> 17:42
>
> Now let's run our program:
>
> *) SILLYSTRCPY
>
> When your program starts its run (on this pretend system), x contains
> any old junk, whatever happened to be in memory, and the following four
> bytes contain the system time (which, for simplicity, I'll represent in
> ASCII).
>
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> | *d *| *% *| *$ *| *` *| *& *| *1 *| *7 *| *4 *| *2 *|
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> <-- 5 bytes reserved for x --> <-- 4 bytes reserved
> * * * * * * * * * * * * * * * * * * for system time -->
>
> Now we execute our strcpy, and here's what happens to the memory (on
> this particular system):
>
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> | *C *| *O *| *M *| *P *| *I *| *L *| *E *| *R *| *\0 |
> +-----+-----+-----+-----+-----+-----+-----+-----+-----+
> <-- 5 bytes reserved for x --> <-- 4 bytes reserved
> * * * * * * * * * * * * * * * * * * for system time -->
>
> We print the string, and printf thinks it's just a string like any
> other, so printf prints everything from the start of x up to the first
> null character, and you see:
>
> COMPILER
>
> on your monitor. The program then ends, and we are back at the prompt:
>
> *)
>
> We are curious to know again what the time is, so we do this:
>
> *) TIME
>
> and the result is:
>
> LER
>
> The program has trashed an important component of the system by
> violating the bounds of its memory. Lesson: Don't Do That.
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line vacant - apply within


you have been understood.

thanks
 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      06-02-2010
iC and iC++ <(E-Mail Removed)> wrote:
> I found this code in a very old book about pointers and I started
> playing with it and I have a question.


> #include <stdio.h>
> #include <string.h>


> main()
> {
> char x[5];
> strcpy(x, "COMPILER");


> printf("%s, %u, %d, \n", x, &x, sizeof(x));


> getchar();
> }


> How deos strcpy assign all the characters in the code if x is only
> defines as a 5 byte array? In other words, where are the extra bytes
> stored and how is memory for them allocated. I looked at it while
> debugging and there were no clues there.


You won't find anything because this use of strcpy() just in-
vokes undefined behaviour. As a programmer you have to ensure
that the buffer you pass to strcpy() as the target is large
enough to hold the string you want to copy to it. In this pro-
gram this isn't the case and the consequences could be anything
- from looking as if everything works fine, a crash of your pro-
gram to your hard disk getting reformatted. So this example
program simply is buggy and should be marked with "Don't do
this at home. kids".

strcpy() simply doesn't have any means of checking if the
source string will fit into the target buffer - all it gets
is two pointers with no information about the sizes of the
buffers. So it has to blindly trust you that you have got
it right and copies everything, including the trailing '\0'
char, from the source string to the destination. If the desti-
nation buffer is too short printf() will blissfully ignorant
of what may be the consequences overwrite the memory following
the end of the destination buffer. If there's something im-
portant to your program (or even the operating system) you
just overwrote it and there's no way to get it back. strcpy()
also can only deduce from the trailing '\0' in the source
buffer when to stop, so if you pass it a char array that
doesn't contain a '\0' (so it's not a string) then you're also
screwed since it won't stop at the end of the source buffer
but happily continues until it finds some '\0' in the memory
following the end of the source buffer.

Perhaps that gets even more clear if you consider a possible
implemention of strcpy():

char *strcpy( char *dest, const char *src )
{
char *ret = dest;
while ( *dest++ = *src++ );
return ret;
}

This is (I think) a perfectly legal implementation of strcpy().
So you will be in trouble when

a) 'dest' is a NULL pointer or does not point to memory you own
b) 'src' is a NULL pointer or does not point to memory you own
c) 'src' isn't a pointer to a string, i.e. there's no '\0'
within the elements of the char array pointed to by 'src'
d) the char array 'dest' is pointing to isn't large enough
to hold all the chars from 'src' up to and including
the terminating '\0; char

So YOU have to take care that this can't happen. You pro-
bably will be careless a few times and will have to spend
a god deal of time figuring out where things went wrong.
In the long run it will make you either a much more careful
programmer or you will switch to a language where this can't
happen. It's like with cooking - things are a lot more fun
if you have really sharp knifes but you have to be on your
toes or you will shed some of your blood (or even lose parts
of your fingers

By the way, also this line is problematic:

> printf("%s, %u, %d, \n", x, &x, sizeof(x));


since the type of 'sizeof(x) isn't necessarily an int
(as you are promising printf() by using the '%d' format
specifier). The result of 'sizeof' is an unsigned integer
type of 'size_t' (note the 'integer' in contrast to 'int'),
so it would be prudent to use '%lu' as the format specifier
and cast the result of 'sizeof' to 'unsigned long' (or use
whatever is the largest unsigned integer type on your machine
unless you have a C99 compliant compiler where there's the
special format specifier of '%z' that tells printf() that it
has to expect a type of 'size_t' as the corresponding argument).

Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
iC and iC++
Guest
Posts: n/a
 
      06-02-2010
On Jun 2, 7:18*pm, Geoff <(E-Mail Removed)> wrote:
> On Wed, 2 Jun 2010 15:57:34 -0700 (PDT), "iC and iC++"
>
> *What is the title of this book and who is the author?


Mastering C Pointers: Tools for programming power by Robert J.
Traister.. 1990

I am writing a tutorial on C pointers and this is one of the better
books I've found..

 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      06-03-2010
On 2010-06-02, iC and iC++ <(E-Mail Removed)> wrote:
> #include <stdio.h>
> #include <string.h>
>
> main()
> {
> char x[5];
> strcpy(x, "COMPILER");
>
> printf("%s, %u, %d, \n", x, &x, sizeof(x));
>
> getchar();
> }


> How deos strcpy assign all the characters in the code if x is only
> defines as a 5 byte array?


By overwriting other stuff, probably. This is certainly welcome to blow up
spectacularly, and will on some hardware.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
strcpy - my implementation arnuld C Programming 64 09-11-2008 12:49 AM
strcpy and the copy constructor RonHiler C++ 8 10-19-2004 06:30 AM
C++ Compiler with a -Wwarn-use-of-strcpy or similar option?? Paul Sheer C++ 4 09-14-2004 08:38 PM
C++ Compiler with a -Wwarn-use-of-strcpy or similar option?? Paul Sheer C++ 7 09-10-2004 05:07 PM
strcpy Mike Mimic C++ 9 05-17-2004 08:12 PM



Advertisments