va_list q

David O'Brien obrien at freebsd.org
Thu Apr 22 08:49:43 PDT 2004


On Wed, Apr 21, 2004 at 09:45:43PM -0700, David O'Brien wrote:
> On Wed, Apr 21, 2004 at 09:53:07AM -0700, Marcel Moolenaar wrote:
> > On Wed, Apr 21, 2004 at 06:51:27PM +0300, Valentin Nechayev wrote:
> > The use of va_arg(args, va_list) works on ia64 (FreeBSD, HP-UX and Linux).
> > Given the limited context, I can only suggest that you try to create a
> > temporary variable of type va_list and change the offending line to:
> > 
> > 	va_list tmpvalist = va_arg(args, va_list);
> > 	n = vslprintf(buf, buflen + 1, f, tmpvalist);
> ..snip..
> > #include <stdarg.h>
> > #include <stdio.h>
> > 
> > int
> > vf2(int count, va_list ap)
> 
> 
> Still wrong:
> 
>     sledge$ cc arg.c 
>     sledge$ ./a.out 
>     Segmentation fault (core dumped)
> 
> your test program isn't ISO-C compliant.

The details:

This code breaks because it is not ISO-C compliant.  Marcel's suggestion
also isn't ISO-C compliant.  One must use va_copy() just like one needs
to use strcpy() to get a unique copy of a C string.  There are two
platforms to date where GCC takes "advantage" of the ISO-C99 standard and
impliments stdargs in a way that depends on compliant code.

Note that the "#ifdef __powerpc__" code is ISO-C compliant and should
work on all platforms.

1. Adhere to ISO C specification for stdargs:

    Do not copy ap directly:
    void foo (va_list ap) {
        va_list tap = ap;
        /* use tap */
    }

    Correct usage:
    #include <stdargs.h>
    void foo (va_list ap) {
        va_list tap;
        va_copy (tap, ap);
        /* use tap */
    }

    GCCs ap is a pointer for AMD64.  &ap does not do what you may expect.

    Review ISO C99 standard, Section 7.15.

-- 
-- David  (obrien at FreeBSD.org)




More information about the freebsd-ia64 mailing list