This is the mail archive of the 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, 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
>      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
>      reference to ap."
>On the other hand, the glibc manual states the following:
>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_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.


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