In some code, I wanted to make argv[0] global for use in error
messages rather than passing it as argument. So I simply made a
global variable and assigned argv[0] to it in main():
char * argv0;
int main(int argc, char * argv[])
{
...
argv0 = argv[0];
...
}
This has always worked for me with gcc-compiled code running on Linux,
but I was wondering if this is a portable assumption. Ie, are the strings
in argv[] specified by standard to reside in global storage (regardless of the
local-to-main() scope of the argv symbol itself).
(Easy to work around if not, just malloc() some space, copy argv[0] into
it, and point argv0 at the malloc() buffer, but I wanted to know if the
C standard had anything to say about the storage class of argv[]
strings. Can I reliably skip this step with standard-compliant
compilers to accomplish the purpose of globalizing access to argv[] strings?)
Regards,
Clayton Weaver
<mailto: cgw...@aol.com>
"Everyone is ignorant, just about different things." Will Rogers
--
comp.lang.c.moderated - moderation address: cl...@plethora.net
> Question about argv[]:
>
> In some code, I wanted to make argv[0] global for use in error
> messages rather than passing it as argument. So I simply made a
> global variable and assigned argv[0] to it in main():
>
> char * argv0;
>
> int main(int argc, char * argv[])
> {
> ...
> argv0 = argv[0];
> ...
> }
>
> This has always worked for me with gcc-compiled code running on Linux,
> but I was wondering if this is a portable assumption. Ie, are the strings
> in argv[] specified by standard to reside in global storage (regardless of the
> local-to-main() scope of the argv symbol itself).
I'm not sure what you mean by `global storage', but the standard does
guarantee that the strings in the argv array are not modified unless you
modify them yourself. 5.1.2.2.1#2:
| [...]
| -- The parameters argc and argv and the strings pointed to by the
| argv array shall be modifiable by the program, and retain their
| last-stored values between program startup and program termination.
IOW, yes, you can do this. However, before you use argv[0] in an error
message, you probably want to make sure that it is not a null pointer,
and that its first character is not a null character. I usually use the
following code in my programs:
#define PROGNAME "whatever"
const char *invocation_name;
int
main (int argc, char *argv [])
{
invocation_name = (argv [0] != 0 && *(argv [0]) != '\0'
? argv [0]
: PROGNAME);
/* ... */
}
Martin
>In some code, I wanted to make argv[0] global for use in error
>messages rather than passing it as argument. So I simply made a
>global variable and assigned argv[0] to it in main():
>
>char * argv0;
>
>int main(int argc, char * argv[])
>{
> ...
> argv0 = argv[0];
> ...
>}
>
>This has always worked for me with gcc-compiled code running on Linux,
>but I was wondering if this is a portable assumption.
it doesn't need to be. it's no different than assigning to a `global'
pointer the address of any other data. the data's scope is that of main,
which is what calls all other functions so they have access to the storage.
>(Easy to work around if not, just malloc() some space, copy argv[0] into
>it, and point argv0 at the malloc() buffer,
only if all you want is argv[0]. argc is an array of pointers to strings.
so you'd have to allocate enough space for all the arguments, either
en-bloc or one-by-one, e.g.,
char **program_args;
int main(int argc, char *argv[]) {
if (0 < argc) {
int i;
program_args = malloc(argc * *program_args);
assert(0 != program_args);
for (i=0; i<argc; i++) {
if (!argv[i]) program_args[i] = 0;
else {
char *temp = malloc(strlen(argv[i])+1);
assert(0 != temp);
strcpy(temp, argv[i]);
program_args[i] = temp;
}
}
}
}
>but I wanted to know if the
>C standard had anything to say about the storage class of argv[]
static.
--
bringing you boring signatures for 17 years
The pointed-to strings retain their last-stored values until
program termination.
>Question about argv[]:
>
>In some code, I wanted to make argv[0] global for use in error
>messages rather than passing it as argument. So I simply made a
>global variable and assigned argv[0] to it in main():
>
>char * argv0;
>
>int main(int argc, char * argv[])
>{
> ...
> argv0 = argv[0];
> ...
>}
>
>This has always worked for me with gcc-compiled code running on Linux,
>but I was wondering if this is a portable assumption. Ie, are the strings
>in argv[] specified by standard to reside in global storage (regardless of the
>local-to-main() scope of the argv symbol itself).
I don't think those arguments are required to be stored in with static
duration, but the memory pointed at by the argv pointers must be
accessible as long as main has not returned to its caller.
So, if you don't try to use argv0 in a function that has been
registered with atexit(), you should be fine.
>
>Regards,
>
>Clayton Weaver
Bart v Ingen Schenau
Even if the storage is local to main, the strings wouldn't be removed from the
stack until main returns, so in practice, they will be valid throughout the life
of the program. Maybe you might run in to trouble if you try to use the string
in an atexit() function--I don't know.
I hope I'm not wrong here, but I've made the assumption that it should work
quite a lot of times and never had a problem (over a reasonable but ordinary
range of compilers).
-Ed
It's required to work even in that case.
Are you sure? According to 5.1.2.2.1#2, the string pointed to by
argv[0] retains its last-stored value until program termination,
so it would even be available to functions registered with atexit.
Martin
>only if all you want is argv[0]. argc is an array of pointers to strings.
grr. `argv is an array ...'
C99 5.1.2.2.1 says:
The parameters argc and argv and the strings pointed to by the
argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program
termination.
How does this interact with functions registered via atexit()? Does
"program termination" occur after those functions are called?
--
Keith Thompson (The_Other_Keith) k...@cts.com <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
The standard does not guarantee that a stack exists. And typical
implementations which do use a stack do *not* put the string pointed
to by argv[0] on the stack.
Martin
The strings aren't in main()'s stack frame.
Yes.
You should be OK. The contents/values of argv/argc are guaranteed
until main() returns --- unless, of course, you modify them.
If you try to do things with them before main() is called, or after it
returns
(eg with atexit type functions) all bets are off.
>Bart van Ingen Schenau <Bart.van.In...@ict.nl> writes:
>>
>> I don't think those arguments are required to be stored in with static
>> duration, but the memory pointed at by the argv pointers must be
>> accessible as long as main has not returned to its caller.
>> So, if you don't try to use argv0 in a function that has been
>> registered with atexit(), you should be fine.
>
>Are you sure?
No.
>According to 5.1.2.2.1#2, the string pointed to by
>argv[0] retains its last-stored value until program termination,
>so it would even be available to functions registered with atexit.
To get a clear picture, the relevant sections are
5.1.2.2.1/2 (parameters to main):
"The parameters argc and argv and the strings pointed to by the argv
array shall be modifiable by the program, and retain their last-stored
values between program startup and program termination."
7.20.4.2/2 (the atexit function):
"The atexit function registers the function pointed to by func, to be
called without arguments at normal program termination."
Because the functions registered with atexit() are called _at_ program
termination, it is not clear to me that the argv strings must still be
valid.
This is because english is not my native language, and I don't know if
the term 'between' includes or excludes the boundaries.
>
>Martin
Bart v Ingen Schenau
(Note: one corner case not mentioned
is a write() to fileno(stderr) that attempts
to write argv[0] from a signal handler
where the signal is received after
exit() is called but before the process
exits, similar to the registered-with-atexit()
issue.)
My conclusion: just malloc() the
buffer and copy non-NULL,
non-empty argv[0] into it up front, at which point there are no more issues
with
the scope of argv[]. The additional
time/space cost will be lost in the noise.
If you don't have malloc() (real-time
maybe), hard code the string.
(Future revisions of the standard might
want to tie it down with an ordering
relative to atexit() in the quoted section, though.)
Regards,
Clayton Weaver
<mailto: cgw...@aol.com>
"Everyone is ignorant, just about different things." Will Rogers
The program has not terminated during atexit-registered
function processing. We thought that was pretty obvious.
|> u98...@ecs.ox.ac.uk (Edward Rosten) writes:
|> > Even if the storage is local to main, the strings wouldn't be
|> > removed from the stack until main returns,
|>
|> The standard does not guarantee that a stack exists. And typical
|> implementations which do use a stack do *not* put the string pointed
|> to by argv[0] on the stack.
I'd guess Unix implementations are not typical then.
Andreas.
--
Andreas Schwab, SuSE Labs, sch...@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Well, it depends on whether you consider the kernel a part of the
C implementation (which I don't).
In some (most?) Unix implementations, GNU/Linux among them, the stack
pointer points to the program argument strings (and environment strings)
when the kernel invokes the program. The startup code then sets up the argv
array based on these strings. In a way, you are correct that the strings
pointed to by the argv elements are on the stack, but the C implementation
didn't put them there (the kernel did).
Martin
>|> > Even if the storage is local to main, the strings wouldn't be
>|> > removed from the stack until main returns,
>|>
>|> The standard does not guarantee that a stack exists. And typical
>|> implementations which do use a stack do *not* put the string pointed
>|> to by argv[0] on the stack.
>
>I'd guess Unix implementations are not typical then.
what's that have to do with what the stack requires / guarantees?
--
bringing you boring signatures for 17 years
>|> > Even if the storage is local to main, the strings wouldn't be
>|> > removed from the stack until main returns,
>|>
>|> The standard does not guarantee that a stack exists. And typical
>|> implementations which do use a stack do *not* put the string pointed
>|> to by argv[0] on the stack.
>
>I'd guess Unix implementations are not typical then.
what's that have to do with what the stack requires / guarantees?
--
bringing you boring signatures for 17 years
Does the standard specify that, or is that an implementation detail?
-Ed
What other data structure could you use to keep track of loops, function calls,
etc?
> And typical
> implementations which do use a stack do *not* put the string pointed
> to by argv[0] on the stack.
You did notice that I said "even *if* storage is local to main", implying that
it isn't usually, but it wouldn't matter if it is?
-Ed
>what's that have to do with what the stack requires / guarantees?
grr. make that:
... with what the standard requires / guarantees?
The standard specifies that, in several ways.
>what's that have to do with what the stack requires / guarantees?
grr. make that:
... with what the standard requires / guarantees?
But the end result is the same, unless you consider the part of the stack
region below the initial frame not to be part of the program's stack.
Since this space can be considered global (it is not deallocated even when
the initial frame ceases to exists) this may be a reasonable view.
Andreas.
--
Andreas Schwab, SuSE Labs, sch...@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."