This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: var-args implementation


At 09:41 14.11.00, HPENNER@de.ibm.com wrote:


>I have a question regarding the var-args implementation in gcc-2.95.2. The
>following program does not work
>right on the S390 platform, since va_list is a pointer to a structure,
>which has some field, which are update by
>va_arg. This is done to keep track of how many register of two different
>classes are already processed
>
>
>int my_printf(char* format,...){
>         va_list ap,
>         va_start(ap, format);
>
>         vfprintf(stderr, format, ap);
>         vfprintf(stdout, format, ap);
>
>         return 1;
>}
>
>The ANSI standard states:
>
>"The object  ap may be passed as an argument to another function; if that
>function
>      invokes the va_arg macro with parameter ap, the value of ap in the
>calling function
>      is indeterminate and shall be passed to the va_end macro prior to any
>further
>      reference to ap."
>
>On the other hand, the glibc manual states the following:
>
>(http://www.gnu.org/manual/glibc-2.0.6/html_chapter/libc_7.html#SEC96)
>
>In some other systems, the va_list pointer may become invalid after the
>call to vprintf, so you must not use va_arg after
>you call vprintf. Instead, you should call va_end to retire the pointer
>from service. However, you can safely call va_start on
>another pointer variable and begin fetching the arguments again through
>that pointer. Calling vprintf does not destroy the
>argument list of your function, merely the particular pointer that you
>passed to it.
>
>GNU C does not have such restrictions. You can safely continue to fetch
>arguments from a va_list pointer after passing it to
>vprintf, and va_end is a no-op. (Note, however, that subsequent va_arg
>calls will fetch the same arguments which
>vprintf previously used.)
>
>
>
>Is the above statement true for all backends? Does a gcc implementation of
>var-args need to be implemented that way, that a callee may not destroy the
>va_list passed?

No, I think the glibc description is simply out-of-date, it's probably only 
true for x86 platforms.
In your code above you have either to use va_copy or va_end/va_start like that:

int my_printf(char* format,...)
{
  va_list ap;
  va_start(ap, format);

  vfprintf(stderr, format, ap);

  va_end(ap);
  va_start(ap, format);

  vfprintf(stdout, format, ap);

  return 1;
}

Otherwise the behaviour is undefined. It would be nice if some native 
speaker could update the glibc documentation accordingly, it seems 
glibc-2.2 still has the same doc.

Franz.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]