Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

argv[] storage always global?

269 views
Skip to first unread message

Clayton Weaver

unread,
Jan 8, 2003, 4:03:20 PM1/8/03
to
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).

(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

Martin Dickopp

unread,
Jan 10, 2003, 2:09:10 AM1/10/03
to
cgw...@aol.com (Clayton Weaver) writes:

> 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

those who know me have no need of my name

unread,
Jan 10, 2003, 2:09:43 AM1/10/03
to
in comp.lang.c.moderated i read:

>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

Douglas A. Gwyn

unread,
Jan 10, 2003, 2:09:52 AM1/10/03
to
Clayton Weaver wrote:
> char * argv0;
> int main(int argc, char * argv[])
> {
> argv0 = argv[0];
> ... 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).

The pointed-to strings retain their last-stored values until
program termination.

Bart van Ingen Schenau

unread,
Jan 10, 2003, 2:09:59 AM1/10/03
to
On 08 Jan 2003 21:03:20 GMT, cgw...@aol.com (Clayton Weaver) wrote:

>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

Edward Rosten

unread,
Jan 11, 2003, 11:57:58 PM1/11/03
to
cgw...@aol.com (Clayton Weaver) wrote in message news:<clcm-2003...@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).
>
> (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?)

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

Douglas A. Gwyn

unread,
Jan 11, 2003, 11:58:16 PM1/11/03
to
Bart van Ingen Schenau wrote:
> So, if you don't try to use argv0 in a function that has been
> registered with atexit(), you should be fine.

It's required to work even in that case.

Martin Dickopp

unread,
Jan 11, 2003, 11:58:35 PM1/11/03
to
Bart van Ingen Schenau <Bart.van.In...@ict.nl> writes:
> On 08 Jan 2003 21:03:20 GMT, cgw...@aol.com (Clayton Weaver) wrote:
> >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.

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

those who know me have no need of my name

unread,
Jan 11, 2003, 11:58:41 PM1/11/03
to
in comp.lang.c.moderated i wrote:

>only if all you want is argv[0]. argc is an array of pointers to strings.

grr. `argv is an array ...'

Keith Thompson

unread,
Jan 11, 2003, 11:59:06 PM1/11/03
to
"Douglas A. Gwyn" <DAG...@null.net> writes:
> Clayton Weaver wrote:
> > char * argv0;
> > int main(int argc, char * argv[])
> > {
> > argv0 = argv[0];
> > ... 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).
>
> The pointed-to strings retain their last-stored values until
> program termination.

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"

Martin Dickopp

unread,
Jan 12, 2003, 6:46:44 PM1/12/03
to
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.

Martin

Douglas A. Gwyn

unread,
Jan 12, 2003, 6:46:50 PM1/12/03
to
Edward Rosten wrote:
> Even if the storage is local to main, the strings wouldn't be removed from the
> stack until main returns, ...

The strings aren't in main()'s stack frame.

Douglas A. Gwyn

unread,
Jan 12, 2003, 6:46:56 PM1/12/03
to
Keith Thompson wrote:
> How does this interact with functions registered via atexit()? Does
> "program termination" occur after those functions are called?

Yes.

Rob

unread,
Jan 13, 2003, 3:51:26 PM1/13/03
to
"Clayton Weaver" <cgw...@aol.com> wrote in message
news:clcm-2003...@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).

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

unread,
Jan 13, 2003, 3:51:37 PM1/13/03
to
On 12 Jan 2003 04:58:35 GMT, Martin Dickopp <firefl...@gmx.net>
wrote:

>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

Clayton Weaver

unread,
Jan 15, 2003, 9:43:44 PM1/15/03
to
Ok, thanks for the insights.

(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

Douglas A. Gwyn

unread,
Jan 16, 2003, 6:42:07 PM1/16/03
to
Clayton Weaver wrote:
> (Future revisions of the standard might
> want to tie it down with an ordering
> relative to atexit() in the quoted section, though.)

The program has not terminated during atexit-registered
function processing. We thought that was pretty obvious.

Andreas Schwab

unread,
Jan 16, 2003, 6:42:27 PM1/16/03
to
Martin Dickopp <firefl...@gmx.net> writes:

|> 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."

Martin Dickopp

unread,
Jan 17, 2003, 5:55:33 PM1/17/03
to
Andreas Schwab <sch...@suse.de> writes:
> Martin Dickopp <firefl...@gmx.net> writes:
>
> |> 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.

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

those who know me have no need of my name

unread,
Jan 17, 2003, 5:55:35 PM1/17/03
to
in comp.lang.c.moderated i read:

>Martin Dickopp <firefl...@gmx.net> writes:
>|> 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.

what's that have to do with what the stack requires / guarantees?

--
bringing you boring signatures for 17 years

those who know me have no need of my name

unread,
Jan 17, 2003, 5:55:34 PM1/17/03
to
in comp.lang.c.moderated i read:

>Martin Dickopp <firefl...@gmx.net> writes:
>|> 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.

what's that have to do with what the stack requires / guarantees?

--
bringing you boring signatures for 17 years

Edward Rosten

unread,
Jan 17, 2003, 5:55:57 PM1/17/03
to
"Douglas A. Gwyn" <DAG...@null.net> wrote in message news:<clcm-2003...@plethora.net>...

> Edward Rosten wrote:
> > Even if the storage is local to main, the strings wouldn't be removed from the
> > stack until main returns, ...
>
> The strings aren't in main()'s stack frame.

Does the standard specify that, or is that an implementation detail?

-Ed

Edward Rosten

unread,
Jan 17, 2003, 5:55:58 PM1/17/03
to
Martin Dickopp <firefl...@gmx.net> wrote in message news:<clcm-2003...@plethora.net>...

> 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.

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

those who know me have no need of my name

unread,
Jan 18, 2003, 1:44:44 PM1/18/03
to
in comp.lang.c.moderated i wrote:

>what's that have to do with what the stack requires / guarantees?

grr. make that:

... with what the standard requires / guarantees?

Douglas A. Gwyn

unread,
Jan 18, 2003, 1:44:40 PM1/18/03
to
Edward Rosten wrote:
> "Douglas A. Gwyn" <DAG...@null.net> wrote in message news:<clcm-2003...@plethora.net>...
>>The strings aren't in main()'s stack frame.
> Does the standard specify that, or is that an implementation detail?

The standard specifies that, in several ways.

those who know me have no need of my name

unread,
Jan 18, 2003, 1:44:46 PM1/18/03
to
in comp.lang.c.moderated i wrote:

>what's that have to do with what the stack requires / guarantees?

grr. make that:

... with what the standard requires / guarantees?

Andreas Schwab

unread,
Jan 20, 2003, 6:27:54 PM1/20/03
to
Martin Dickopp <firefl...@gmx.net> writes:

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."

0 new messages