stdarg: safe to pass va_list * and have callees va_arg(*args, type)??

Lawrence Kirby fred@genesis.demon.co.uk
Fri Oct 1 00:00:00 GMT 1999


In article < 877lmgwz3c.fsf@pfaffben.user.msu.edu >
           pfaffben@msu.edu "Ben Pfaff" writes:

>slevy@ncsa.uiuc.edu (Stuart Levy) writes:
>
>   I'm working with a C program that makes lots of use of stdarg in the
>   following way.  It *looks* legal to me, and has worked correctly with many
>   compilers.   But, some recent versions of egcs (something for PPC, and
>   egcs 1.0 for x86) seem to generate incorrect code -- at least, they yield
>   *some* wildly incorrect values from va_arg() (and many correct values).
>
>   I'm seeking advice on whether that should be considered a
>   compiler/runtime-system bug, or whether this is really an unsafe construct.
>   (If the former, I'll try to make a real test case and submit a bug report.)
>
>   Briefly, a stdarg-using routine is passing the *address* of its
>   va_list pointer to various functions, expecting them to update it as
>   they grab arguments from it, then grabbing more arguments itself, etc.
>
>This is an odd example of synchronicity.  I was just wrestling with a
>related, but not identical, issue myself about an hour ago.
>Fortunately, I have a copy of the Standard at hand, with which I was
>able to straighten myself out.
>
>Basically, the Standard says that va_list is an opaque type.

Nevertheless it is an object type.

> There
>are only two things that you're guaranteed to be able to do with it in
>standard C (after you've initialized it with va_start), AFAICT from
>the Standard:
>
>        1. Pass it to va_arg and va_end directly.
>        2. Pass it as an argument to another function.

The standard talks specifically about the "object ap". I interpret this to
mean that any lvalue designating that object is valid. 

>In case (2), it says that if the called function calls va_arg, then
>the value of the va_list in the caller is indeterminate and that
>va_end must be called afterward, rather than va_arg.

The problem here probably stems from the fact that va_list may or may not
be an array type so the object in the caller may or may not by updated
by the called function. By passing a pointer to the object you ensure that
the called function does modify the object in the caller.

>The Standard doesn't seem to define what you can do with a pointer to
>a va_list, so I think that that would be undefined behavior.

A pointer to a va_list is a pointer to an object so behaves just like
any other pointer to an object. IMO this technique should work.

-- 
-----------------------------------------
Lawrence Kirby | fred@genesis.demon.co.uk
Wilts, England | 70734.126@compuserve.com
-----------------------------------------



More information about the Gcc-help mailing list