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