Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!wuarchive!cs.utexas.edu!yale!cmcl2!adm!smoke!gwyn From: gwyn@smoke.BRL.MIL (Doug Gwyn) Newsgroups: comp.unix.questions Subject: Re: Strcpy on SysV vs. BSD. Message-ID: <13724@smoke.BRL.MIL> Date: 2 Sep 90 03:39:40 GMT References: <24351@adm.BRL.MIL> Followup-To: comp.lang.c Organization: U.S. Army Ballistic Research Laboratory, APG, MD. Lines: 55 In article <24351@adm.BRL.MIL> hsw@sparta.com (Howard Weiss) writes: >main(){ > char *TTx = "/dev/"; > char tty[10]; /* works on both SysV and BSD */ >/* char *tty; /* works only on BSD */ > strcpy(tty,TTx); > printf("what's in tty now is %s\n",tty); >} >When I tried using the above program on SysV with the 'char *tty;' >declaration, it compiles fine, but core dumps when run. The same >thing occurs if I substitute 'while (*tty++ = *TTx++)' in place of the >library strcpy. Yet, the 'char *tty' compiles and runs fine on BSD! >To get this to work on SysV, I used the 'char tty[10]' declaration. >Any words of wisdom as to why this is the case would be appreciated! >I've worked on UNIX systems since V6 (in 1976) and I've never seen >this before. Heavens, you've made one of the most common blunders made by novice C programmers. In the pointer form of the example, the "tty" variable is not made to point to valid storage and in fact could contain arbitrary garbage, since it has never been initialized. When you supply this garbage-valued pointer to strcpy(), strcpy() attempts to use it to point into the target for the copied characters, with unpredictable results. Apparently one of the systems you tried this on happens to not fail very miserably, while the other one does. The program is, however, not correct for any system. The following rewrite contains some instructive comments: #include /* required for printf() */ #include /* to properly declare strcpy() */ int /* (making this explicit is optional) */ main( argc, argv ) /* ANSI C permits main() to optionally have no arguments, but old C doesn't */ int argc; /* (making this explicit is optional) */ char *argv[];/* or char **argv; which is equivalent for function parameters, but NOT the same thing elsewhere */ { static /* might as well let the linker init it */ char TTx[] = /* no sense in using a pointer where the array name itself could be used */ "/dev/";/* initial contents of the TTx[6] array */ char tty[10];/* allocates auto storage for 10 chars */ char *tp = tty; /* METHOD 2: points to tty[0] */ (void) /* (making this explicit is optional) */ strcpy( tty, TTx ); /* copy 6 chars into tty[.] */ (void)strcpy( tp, TTx );/* METHOD 2; same result */ (void) /* (making this explicit is optional) */ printf( "What's in the initial part of tty[] is \"%s\"\n", tty /* or tp */ ); return 0; /* return "successful" exit status */ }