From eagle!jmh Thu Jun 2 01:53:00 BST 1988 Article 21 of ukc.unix.help: Path: raven!eagle!jmh >From: jmh@eagle.ukc.ac.uk (Jim Hague) Newsgroups: ukc.unix.help Subject: Re: execvp() problem Message-ID: <5147@eagle.ukc.ac.uk> Date: 1 Jun 88 20:15:08 GMT References: <5145@eagle.ukc.ac.uk> Reply-To: jmh@ukc.ac.uk (Jim Hague) Distribution: ukc Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 94 In article <5145@eagle.ukc.ac.uk> arc1@ukc.ac.uk (A.R.Curtis) writes: > >{ > char args[5][10]; > > strcpy(args[0], "ls"); > strcpy(args[1], "-lg"); > strcpy(args[2], "/bin"); > strcpy(args[3], ""); > > execvp(args[0], args); >} > > >As far as I can see from the execl... man page this is >correct, yet when I run it, the exec() fails and errno is 14 >(EFAULT). args[] appears to be null-terminated, and args[0] >is "ls", so what am I doing wrong? Try this - turgid explanation follows .... { char *args[5]; args[0] = "ls"; args[1] = "-lg"; args[2] = "/bin"; args[3] = NULL; execvp(args[0], args); } ** BEWARE - Frumious Turgid Explanation ** (I hope it's right) The second parameter demanded by execvp is an array of pointers to strings, char *argv[] in C. Null-terminated means the last entry must be must be a null pointer. Pictorially, what we want is ... +----+ | | -> "ls" +----+ | | -> "-lg" +----+ | | -> "/bin" +----+ |NULL| +----+ Now, this is *not* the same thing as a multi-dimensional array. char args[5][10] merely reserves, umm, space for 50 chars, conceptually arranged thus (with the results of the strcpys filled in). EOS = \0 = End Of String. +---+---+---+---+---+---+---+---+---+---+ | l | s |EOS| | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | - | l | g |EOS| | | | | | | +---+---+---+---+---+---+---+---+---+---+ | / | b | i | n |EOS| | | | | | +---+---+---+---+---+---+---+---+---+---+ |EOS| | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ If fact, they'll all be laid out in memory one row after the other, +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ .... | l | s |EOS| | | | | | | | - | l | g |EOS| .... +---+---+---+---+---+---+---+---+---+---+---+---+---+---+ .... The crucial thing is that there is not a pointer in sight. Much less a null pointer. There is a null string, "", but that's different. You can sometimes behave as if there were pointers in there, but there isn't the vector of pointers you wanted. So, why do the strcpys work ? After all, strcpy requires a pointer to char(s), doesn't it ? Gulp, deep breath. The C pointer/array tar-pit glistens wickedly ... When having dealings with arrays, C prefers to throw about pointers to those arrays. The declaration char foo[5] reserves space for 5 characters. Future references to foo unqualified by [] deal with a pointer to those 5 characters. So the variable foo can be treated as a char pointer (wild waving of hands). Now, you have a two-dimensional array of chars, as above. You refer to one row of that array, say args[2]. The compiler notices you're referring to a vector of chars and passes the appropriate pointer (more wild waving of hands). An oversimplification, but it's something like that.