Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Preserving copies of va_list

658 views
Skip to first unread message

Martin Shepherd

unread,
Aug 20, 1993, 2:17:18 AM8/20/93
to

[This is a modified re-post of an article that I cancelled a moment ago,
my apologies to those who have already read the flawed original]

If one has a function like vfprintf() that takes a va_list argument, and
in turn sends that va_list argument separately to two other functions,
is there any portable way of preserving a copy of the va_list argument so
that it can be re-used in the second function?

The problem is that va_end() and va_start() can only be invoked in the
parent function that accepted the varying number of arguments, so
there is apparently no way to re-initialize the list from within a
called function.

On page 210 of the book - "The standard C library", P.J. Plaugher
appears to say that this can be portably accomplished by copying the
va_list object with memcpy() before it is modified, "...regardless of
the type defined for va_list".

This would lead to something like the following:

#include <stdarg.h>
#include <string.h>

int a(va_list ap)
{
va_list ap2; /* A copy of the sent argument list, ap */
/*
* Copy the argument list "value" using memcpy().
*/
memcpy(&ap2, &ap, sizeof(va_list));
/*
* Send ap to the first called function and ap2 to the second.
*/
func1(ap);
func2(ap2);
return 0;
}

Is the above method really as portable as suggested? I can conceive
of a conforming implementation that defined va_list as a pointer to a
structure (assigned by va_start) containing parameters that are
modified by va_arg(). In such an implementation the use of va_arg
would effectively modify both ap and ap2 through the copied pointer
and make ap2 unusable by the second function. Is there anything in the
standard that rules this out and makes the memcpy method portable, or
better still, guaranteed to work?

If not, is there a better way to achieve the same effect portably?

Martin Shepherd (m...@phobos.caltech.edu)

Stephen R. van den Berg

unread,
Aug 24, 1993, 7:55:35 AM8/24/93
to
In article <251q9e...@gap.caltech.edu> m...@goblin.caltech.edu writes:
>If one has a function like vfprintf() that takes a va_list argument, and
>in turn sends that va_list argument separately to two other functions,
>is there any portable way of preserving a copy of the va_list argument so
>that it can be re-used in the second function?

>The problem is that va_end() and va_start() can only be invoked in the
>parent function that accepted the varying number of arguments, so
>there is apparently no way to re-initialize the list from within a
>called function.

>int a(va_list ap)


>{
> va_list ap2; /* A copy of the sent argument list, ap */

> memcpy(&ap2, &ap, sizeof(va_list));
> func1(ap);
> func2(ap2);
> return 0;
>}

This is of course needlessly complex. I'm not sure about the fact
if the above is ANSI compliant or not, but, since you are passing
the va_list argument *by value* anyway, there is no need to go through
such contortions to use memcpy().

The following should suffice:

int a(va_list ap)
{ func1(ap);
func2(ap);
return 0;
}

The copies are implicitly made by passing ap by value.

>Is the above method really as portable as suggested? I can conceive
>of a conforming implementation that defined va_list as a pointer to a
>structure (assigned by va_start) containing parameters that are
>modified by va_arg(). In such an implementation the use of va_arg
>would effectively modify both ap and ap2 through the copied pointer
>and make ap2 unusable by the second function.

I'm not sure what ANSI says about this, but, I think that your worries
are justified.

Though, having implemented a stdarg implementation myself, I can say
that "quality" implementations allow the usage that you want. I.e. the
implementor usually makes sure that all the changing data is in a struct
that hides behind the va_list type. This means that by copying the
va_list variable, you have copied enough state information to parse the
variable list of arguments independently for a second time.
--
Sincerely, be...@pool.informatik.rwth-aachen.de
Stephen R. van den Berg (AKA BuGless). be...@physik.tu-muenchen.de

"Be spontaneous!"

Peter Holzer

unread,
Aug 24, 1993, 10:49:10 AM8/24/93
to
be...@pool.informatik.rwth-aachen.de (Stephen R. van den Berg) writes:

>In article <251q9e...@gap.caltech.edu> m...@goblin.caltech.edu writes:
>>If one has a function like vfprintf() that takes a va_list argument, and
>>in turn sends that va_list argument separately to two other functions,
>>is there any portable way of preserving a copy of the va_list argument so
>>that it can be re-used in the second function?

>>int a(va_list ap)


>>{
>> va_list ap2; /* A copy of the sent argument list, ap */
>> memcpy(&ap2, &ap, sizeof(va_list));
>> func1(ap);
>> func2(ap2);
>> return 0;
>>}

>This is of course needlessly complex. I'm not sure about the fact
>if the above is ANSI compliant or not, but, since you are passing

Neither am I. Va_list is extremely magic.

>the va_list argument *by value* anyway, there is no need to go through
>such contortions to use memcpy().

>The following should suffice:

>int a(va_list ap)
>{ func1(ap);
> func2(ap);
> return 0;
>}

>The copies are implicitly made by passing ap by value.

No. va_list could be an array type, in which case func1 could modify
ap. Func2 would then receive the modified value.

--
| _ | Peter J. Holzer | Think of it |
| |_|_) | Technical University Vienna | as evolution |
| | | | Computer Science/Real-Time Systems | in action! |
| __/ | h...@vmars.tuwien.ac.at | Tony Rand |

Clive Feather

unread,
Aug 24, 1993, 1:01:30 PM8/24/93
to
> If one has a function like vfprintf() that takes a va_list argument, and
> in turn sends that va_list argument separately to two other functions,
> is there any portable way of preserving a copy of the va_list argument so
> that it can be re-used in the second function?

Simple answer - no. The only thing that can safely be done with a
va_list is to pass it as a parameter, or to give it to va_arg and
va_end.

> The problem is that va_end() and va_start() can only be invoked in the
> parent function that accepted the varying number of arguments, so
> there is apparently no way to re-initialize the list from within a
> called function.

Right.

> On page 210 of the book - "The standard C library", P.J. Plaugher
> appears to say that this can be portably accomplished by copying the
> va_list object with memcpy() before it is modified, "...regardless of
> the type defined for va_list".

If this is what Plauger is saying, he is wrong. I suspect, however, he
is talking about his sample implementation only. I don't have my copy to
hand.

> Is the above method really as portable as suggested? I can conceive
> of a conforming implementation that defined va_list as a pointer to a
> structure (assigned by va_start) containing parameters that are
> modified by va_arg().

I can find nothing to prohibit this.

> If not, is there a better way to achieve the same effect portably?

Why not define your function to take *two* va_list objects; there is
nothing to stop the caller from calling va_start twice on its arguments,
and passing you two lists (which, for that matter, need not be in step -
this might be a useful feature for you).

--
Clive D.W. Feather | IXI Ltd (an SCO company) | If you lie to the compiler,
cl...@x.co.uk | Vision Park | it will get its revenge.
Phone: +44 223 236 555 | Cambridge CB4 4ZR | - Henry Spencer
Fax: +44 223 236 466 | United Kingdom |

Martin Shepherd

unread,
Aug 24, 1993, 7:18:17 PM8/24/93
to

The concensus of all the replies that I have received is that there is
no portable way to preserve a copy of a va_list between uses. (There
would be no real need for va_start and va_end if there were). My worry
that the va_list might point into a hidden area was borne out in an
E-mail from Chris Torek - who said that the Pyramid compiler used to
(and may still) make the (varargs) va_alist point into such an area.

In article <CC9w...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>In article <251q9e...@gap.caltech.edu> m...@goblin.caltech.edu writes:

> [Many lines deleted]


>> If not, is there a better way to achieve the same effect portably?
>
>Why not define your function to take *two* va_list objects; there is
>nothing to stop the caller from calling va_start twice on its arguments,
>and passing you two lists (which, for that matter, need not be in step -
>this might be a useful feature for you).
>

Unfortunately I have no control over the arguments sent to this
function so this is not an option. Even if it were, I have been
tentatively informed that although the Rational says that you can have
more than one va_list active at a time - the standard does not appear
to guarantee it - would anybody care to comment on this?

>--
>Clive D.W. Feather | IXI Ltd (an SCO company) | If you lie to the compiler,
>cl...@x.co.uk | Vision Park | it will get its revenge.
>Phone: +44 223 236 555 | Cambridge CB4 4ZR | - Henry Spencer
>Fax: +44 223 236 466 | United Kingdom |

The actual problem was that I had to write a function having identical
arguments to vfprintf which, itself, had to pass those arguments
on to two vfprintf's. The obvious solution, to use vsprintf to
write into a buffer and fwrite the buffer twice to the two streams, is
dangerous because there is no way to know in advance the buffer size
required. The solution that I finally adopted was to write a function
that parses the format, and writes each argument and intervening text,
one at a time into a buffer (using sprintf) - after checking that the
conversion won't overflow this 512-char buffer - and sends each
converted item to an output function. The output function then sends
the buffer to two fwrite()s. This is a sledge hammer approach to the
problem, but it was the only safe and portable method that I could
think of.

[The choice of buffer size was based on Jutta Deneger's observation
that the standard specifies that a conforming C compiler can reject
code that produces more than 509 characters per printf conversion.]

Thanks to Chris Torek, Jutta Deneger and David Spuler for E-mail
discussions.

PS. Does anybody know how a %10n printf format directive should behave?
Should it include the 10 character padding in the character count
(as the SUN implementation does)? Also, should %hn assign to a
(short *) argument or should %n ignore length modifiers?

Martin Shepherd (m...@phobos.caltech.edu)

Karl Heuer

unread,
Aug 25, 1993, 12:17:15 PM8/25/93
to
In article <25e7jp...@gap.caltech.edu> m...@goblin.caltech.edu (Martin Shepherd) writes:
>PS. ...

Btw, when you want to introduce a new subject, it's generally better to post
a separate article rather than making it a postscript to the something else.
Then we can have reasonably accurate and consistent subject lines.

>Does anybody know how a %10n printf format directive should behave?

>Should it include the 10 character padding in the character count?

What padding? Are you saying that some implementations will do *output* when
they see this directive? I don't have the Standard at hand, but I would bet
that this is not correct behavior.

>Also, should %hn assign to a (short *) argument or should %n ignore length
>modifiers?

This one I do know. %hn, %n, %ln expect arguments of type short int, int, and
long int, respectively.

Karl W. Z. Heuer (ka...@osf.org), The Walking Lint

Clive Feather

unread,
Aug 25, 1993, 4:27:34 PM8/25/93
to
In article <25e7jp...@gap.caltech.edu> m...@goblin.caltech.edu (Martin Shepherd) writes:
> In article <CC9w...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>> Why not define your function to take *two* va_list objects; there is
>> nothing to stop the caller from calling va_start twice on its arguments,
>> and passing you two lists (which, for that matter, need not be in step -
>> this might be a useful feature for you).
> Unfortunately I have no control over the arguments sent to this
> function so this is not an option.

If that's really the case, then your stuck. Are you sure you can't
negotiate with the author of the caller ?

> Even if it were, I have been
> tentatively informed that although the Rational says that you can have
> more than one va_list active at a time - the standard does not appear
> to guarantee it - would anybody care to comment on this?

There's no wording in the standard to forbid it, and I can't see any
reason, offhand, why it shouldn't be possible. The only arguments I've
ever heard on this turn out to be easily demolished (they tend to assume
things like va_start containing an unbalanced { matched by a } in
va_end, which it is easy to prove is not a conforming implementation).

> The actual problem was that I had to write a function having identical
> arguments to vfprintf which, itself, had to pass those arguments
> on to two vfprintf's. The obvious solution, to use vsprintf to
> write into a buffer and fwrite the buffer twice to the two streams, is
> dangerous because there is no way to know in advance the buffer size
> required. The solution that I finally adopted was to write a function
> that parses the format, and writes each argument and intervening text,
> one at a time into a buffer (using sprintf) - after checking that the
> conversion won't overflow this 512-char buffer - and sends each
> converted item to an output function. The output function then sends
> the buffer to two fwrite()s.

If you are parsing the format, you can determine the maximum length of
each item fairly simply, and malloc up a single buffer for the vsprintf.

Alternatively, why not vfprintf the arguments to a temporary file
opened with tmpfile(), rewind the file, and copy its contents to the two
output files, or read it into a string, or ...

>[The choice of buffer size was based on Jutta Deneger's observation
> that the standard specifies that a conforming C compiler can reject
> code that produces more than 509 characters per printf conversion.]

True, but not a safe assumption to make if you want to make your code
easy to debug.

Martin Shepherd

unread,
Aug 26, 1993, 7:18:39 PM8/26/93
to
In article <25g3ab$3...@paperboy.osf.org> ka...@dme3.osf.org (Karl Heuer) writes:
>In article <25e7jp...@gap.caltech.edu> m...@goblin.caltech.edu (Martin Shepherd) writes:
>>PS. ...
>
>Btw, when you want to introduce a new subject, it's generally better to post
>a separate article rather than making it a postscript to the something else.
>Then we can have reasonably accurate and consistent subject lines.
>

Point taken.

>>Does anybody know how a %10n printf format directive should behave?
>>Should it include the 10 character padding in the character count?
>
>What padding? Are you saying that some implementations will do *output* when
>they see this directive? I don't have the Standard at hand, but I would bet
>that this is not correct behavior.

The SunOS 4.* standard library, which doesn't claim to be ANSI
compliant, does do such padding, and includes the padding in the
assigned character count.

The first integer of all format directives is described in the
standard, as specifying a minimum field width, with no qualifications
on the conversion specifiers that it relates to. The specific
discussion of the %n directive doesn't rescind it either, so I assume
that this IS the correct behaviour? Also note that this implies that
the %% and %c directives also do this, such that "%10%" produces
" %".

>
>>Also, should %hn assign to a (short *) argument or should %n ignore length
>>modifiers?
>
>This one I do know. %hn, %n, %ln expect arguments of type short int, int, and
>long int, respectively.

This is certainly the way that I interpretted it and is the method
adopted in Plauger's implmentation of printf, but I was surpised
to find that the SunOS 4.* printf only works with (int *) arguments -
regardless of the length modifier - it core dumps if sent a (short *)
with %hn.

>
>Karl W. Z. Heuer (ka...@osf.org), The Walking Lint

Martin Shepherd (m...@phobos.caltech.edu)

Ronald F. Guilmette

unread,
Aug 28, 1993, 3:59:41 AM8/28/93
to
In article <CC9w...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>In article <251q9e...@gap.caltech.edu> m...@goblin.caltech.edu writes:
>> If one has a function like vfprintf() that takes a va_list argument, and
>> in turn sends that va_list argument separately to two other functions,
>> is there any portable way of preserving a copy of the va_list argument so
>> that it can be re-used in the second function?
>
>Simple answer - no. The only thing that can safely be done with a
>va_list is to pass it as a parameter, or to give it to va_arg and
>va_end.
>
...

>> Is the above method really as portable as suggested? I can conceive
>> of a conforming implementation that defined va_list as a pointer to a
>> structure (assigned by va_start) containing parameters that are
>> modified by va_arg().
>
>I can find nothing to prohibit this.

I find these assertions rather alarming, because I have in the past written
code which copied va_lists.

But I'm forced to agree with the conclusion that there is no way to make
such a copy in a way which is guarranteed to be portable.

As a matter of fact, now that I know just how little is guaranteed regarding
the va_list type, I'm inclined to begin to wonder about many other standard
types. Is it equally possible (and permissible) that the following types
might contain pointers to shared structures such that making copies of
values of these types (and then operating on more than one of the copies)
would yield surprizing results?

struct lconv
jmp_buf
FILE
fpos_t
div_t
ldiv_t

(I have of course left out all types defined in "standard" header files
which are required to be integral types.)

Regardless of the status of the above types, I must say that I regard the
fact that it is not possible to make *independent* copies of va_lists as
a flaw in the standard. I hope it will be corrected at some future date.

--

-- Ronald F. Guilmette ------------------------------------------------------
------ domain address: r...@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------

Larry Jones

unread,
Aug 28, 1993, 11:10:39 AM8/28/93
to
In article <25jgcf...@gap.caltech.edu>, m...@goblin.caltech.edu (Martin Shepherd) writes:
> The first integer of all format directives is described in the
> standard, as specifying a minimum field width, with no qualifications
> on the conversion specifiers that it relates to. The specific
> discussion of the %n directive doesn't rescind it either, so I assume
> that this IS the correct behaviour? Also note that this implies that
> the %% and %c directives also do this, such that "%10%" produces
> " %".

Note that the definition of ``field width'' states:

If the converted value has fewer characters than the field
width, it will be padded with spaces (by default)...

Note also that the description of the conversion specifier ``n'' states:

No argument is converted.

If no argument is converted, then there's no converted value to pad, so
%n most definitely does NOT produce any output characters under any
circumstances. Also note that the description of the ``%'' conversion
specifier states:

The complete conversion specification shall be %%.

Thus, ``%10%'' produces undefined behavior. %c, on the other hand, is
well defined and the requested field width is, indeed, honored.

> >>Also, should %hn assign to a (short *) argument or should %n ignore length
> >>modifiers?
> >
> >This one I do know. %hn, %n, %ln expect arguments of type short int, int, and
> >long int, respectively.

Actually, they expect arguments of type POINTER TO short int, int, and
long int. That is clearly spelled out in the descriptions of the ``h''
and ``l'' modifiers.
----
Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH 45150-2789 513-576-2070
larry...@sdrc.com
Ever notice how tense grown-ups get when they're recreating? -- Calvin

Mark Brader

unread,
Aug 28, 1993, 2:33:50 PM8/28/93
to
> > Even if it were, I have been
> > tentatively informed that although the Rational says that you can have
> > more than one va_list active at a time - the standard does not appear
> > to guarantee it - would anybody care to comment on this?
>
> There's no wording in the standard to forbid it, and I can't see any
> reason, offhand, why it shouldn't be possible. ...

That's my opinion also. This would be a good subject for an Interpretation
Ruling (oops, Defect Report).

Someone else posted code where the va_list ap was just copied into ap2
and calls like
func1(ap);
func2(ap2);
were made. That's definitely non-conforming, assuming that func1() does
what we expect it to. From 4.8 (ANSI) / 7.8 (ISO):

# If access to the varying arguments is desired, the called function
# shall declare an object (referred to as ap in this section) having
# type va_list. 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.

The code

/* va_start (ap); done already */
func1 (ap);
va_end (ap);
va_start (ap);
func2 (ap);
/* va_end (ap); done later */

should be an adequate replacement for the above, though the standard
also doesn't explicitly say that you can do that. Has there been an
interpretation ruling on it? I have an impression there may have been,
but I'm posting from home and have no information in rulings here.
Of course, it doesn't solve the original poster's problem anyway.
--
Mark Brader "It is one thing to praise discipline,
SoftQuad Inc., Toronto and another to submit to it."
utzoo!sq!msb, m...@sq.com -- Miguel de Cervantes, 1613

This article is in the public domain.

Mark Brader

unread,
Aug 28, 1993, 3:20:21 PM8/28/93
to
> Is it equally possible (and permissible) that the following types
> might contain pointers to shared structures such that making copies of
> values of these types (and then operating on more than one of the copies)
> would yield surprising results?

There is a second reason why making a copy of the object might not work;
it might also be the case that the address of the object is significant.
I'll give a yes answer below if either reason applies.


> struct lconv

My answer is a qualified yes. Section 4.4.2.1 (ANSI) / 7.4.2.1 (ISO)
says that localeconv() returns a pointer to an internal struct, whose
contents may be overwritten by subsequent calls to localeconv() or
setlocale(). The struct contains a number of pointers, and no
guarantees are made as to the permanence of the data they point to.

However, I think it's clear that the *intent* of 4.4.2.1/7.4.2.1 is
that the pointed-to data may be overwritten only in the circumstances
when the struct may be overwritten, and since there are no guarantees
to the contrary, programs should assume it might be.

In other words, given:

struct lconv *lcp1, *lcp2;
char *cp1, *cp2;
char save[MAXSAVE]+1;

lcp1 = localeconv();
cp1 = lcp1->int_curr_symbol;
if (strlen(cp1) <= MAXSAVE) strcpy (save, cp1);

setlocale (LC_ALL, new_locale);
lcp2 = localeconv();
cp2 = lcp2->int_curr_symbol;

it is possible not only that lcp1 == lcp2, but also that cp1 == cp2, and
even if cp1 != cp2 and the strcpy() took place, that strcmp (save, cp1)
would return nonzero.

On the other hand, if localeconv() and setlocale() are not called again,
then my interpretation is that the pointed-to data is safe from overwriting.


> jmp_buf

My answer is a qualified yes. 4.6/7.6 says that jmp_buf "is an array
type suitable for holding the information needed to restore a calling
environment", and 4.6.1.1/7.6.1.1 says that setjmp() "saves its calling
environment in jmp_buf". Notice the word "in"; I take this to mean that
jmp_buf cannot contain a pointer to the real data elsewhere.

However, 4.6.2.1/7.6.2.1 says that longjmp() restores the environment
saved by the most recent setjmp() "with the corresponding jmp_buf argument".
Since jmp_buf is guaranteed to be an array object, this means that what
longjmp() actually receives is a pointer to its first element, and
therefore it is able to distinguish whether the jmp_buf that you pass
it is the same one that you passed to setjmp(), or a copy. In other
words, the address of the jmp_buf may be significant..

I would consider such an implementation to be of low quality, but I think
it would take an official ruling to say that it was nonconforming.


> FILE

The answer is definitely yes. 4.9.3/7.9.3 says that "The address of
the FILE object used to control a stream may be significant; a copy
of a FILE object may not necessarily serve in place of the original."

(The fact that no similar requirement is stated for jmp_buf objects
in 4.6.*/7.6.*, whereas this is explicitly stated, might serve as grounds
for a ruling that jmp_buf objects do not work that way. I would be happy
if there was such a ruling.)


> fpos_t

My answer is no. 4.9.1/7.9.1 says that fpos_t "is an object type
capable of recording all the information needed to specify uniquely
every position within a file", so it should not contain a pointer;
and 4.9.9.1/7.9.9.1 and 4.9.9.3/7.9.9.3 say that fgetpos() and fsetpos()
work with the *value* of objects of this type. Thus a copy will serve
as well as the original.


> div_t
> ldiv_t

The answer is definitely no. 4.10.6.2/7.10.6.2 and 4.10.6.4/7.10.6.4
state that each of these struct types contain two members having
certain integral types and certain names. The structs are returned
by value from div() and ldiv(), so there can be nothing peculiar about
the behavior of those members. No other members are specified to be
in the structs, so a program cannot assume that there are any others,
and even if there were, copying the struct could not affect the members
with integral types.
--
Mark Brader, SoftQuad Inc., Toronto "When you say 'non-trivial', can you
utzoo!sq!msb, m...@sq.com quantify that for me?" --Kate Hamilton

Ronald F. Guilmette

unread,
Aug 29, 1993, 2:12:57 PM8/29/93
to
In article <34...@heimdall.sdrc.com> scj...@thor.sdrc.com (Larry Jones) writes:
>In article <25jgcf...@gap.caltech.edu>, m...@goblin.caltech.edu (Martin Shepherd) writes:
>> The first integer of all format directives is described in the
>> standard, as specifying a minimum field width, with no qualifications
>> on the conversion specifiers that it relates to. The specific
>> discussion of the %n directive doesn't rescind it either, so I assume
>> that this IS the correct behaviour? Also note that this implies that
>> the %% and %c directives also do this, such that "%10%" produces
>> " %".
>
>Note that the definition of ``field width'' states:
>
> If the converted value has fewer characters than the field
> width, it will be padded with spaces (by default)...
>
>Note also that the description of the conversion specifier ``n'' states:
>
> No argument is converted.
>
>If no argument is converted, then there's no converted value to pad, so
>%n most definitely does NOT produce any output characters under any
>circumstances.

Larry,

I just want to make sure I understand what you're saying.

Are you asserting that a format specifier of (say) %9n always produces
undefined behavior?

Ronald F. Guilmette

unread,
Aug 29, 1993, 2:19:15 PM8/29/93
to
In article <1993Aug28.1...@sq.sq.com> m...@sq.sq.com (Mark Brader) writes:
>> Is it equally possible (and permissible) that the following types
>> might contain pointers to shared structures such that making copies of
>> values of these types (and then operating on more than one of the copies)
>> would yield surprising results?
>
...

>However, 4.6.2.1/7.6.2.1 says that longjmp() restores the environment
>saved by the most recent setjmp() "with the corresponding jmp_buf argument".
>Since jmp_buf is guaranteed to be an array object, this means that what
>longjmp() actually receives is a pointer to its first element, and
>therefore it is able to distinguish whether the jmp_buf that you pass
>it is the same one that you passed to setjmp(), or a copy. In other
>words, the address of the jmp_buf may be significant..
>
>I would consider such an implementation to be of low quality...

For whatever it's worth, I would likewise consider it to be a sign of low
quality if an implementation's design of the va_list type was such that
one could not make (and use) copies of a value of that type without
affecting the original.

Larry Jones

unread,
Aug 30, 1993, 11:14:23 AM8/30/93
to
In article <rfgCCJ...@netcom.com>, r...@netcom.com (Ronald F. Guilmette) writes:
> In article <34...@heimdall.sdrc.com> scj...@thor.sdrc.com (Larry Jones) writes:
> >If no argument is converted, then there's no converted value to pad, so
> >%n most definitely does NOT produce any output characters under any
> >circumstances.
>
> Are you asserting that a format specifier of (say) %9n always produces
> undefined behavior?

No, I'm asserting that it produces well-defined behavior such that the
field width is irrelevant and hence ignored.

One can certainly argue that %9n produces undefined behavior based on
the standard omitting any explicit definition of the behavior; in that
case, the implementation is free to do anything at all, including
producing output characters in clear violation of the intent of the
Standard.


----
Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH 45150-2789 513-576-2070
larry...@sdrc.com

Mom would be a lot more fun if she was a little more gullible. -- Calvin

Norman Diamond

unread,
Sep 1, 1993, 1:41:55 AM9/1/93
to
In article <CCC0t...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>In article <25e7jp...@gap.caltech.edu> m...@goblin.caltech.edu (Martin Shepherd) writes:
>> I have been
>> tentatively informed that although the Rational says that you can have
>> more than one va_list active at a time - the standard does not appear
>> to guarantee it - would anybody care to comment on this?

>There's no wording in the standard to forbid it, and I can't see any
>reason, offhand, why it shouldn't be possible.

ANSI Classic section 4.8.1.2 (va_arg) page 123 lines 43 to 44: "The
parameter ap shall be the same as the va_list ap initialized by va_start."
If two different va_list objects are initialized by two invocations of
va_start, then the parameter ap cannot be the same as both of them.
I thought that a defect report was going to ask about this?
--
<< If this were the company's opinion, I would not be allowed to post it. >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will. Force = program size * destruction.
Every technical corrigendum is met by an equally troublesome new defect report.

David Adrien Tanguay

unread,
Sep 2, 1993, 3:13:06 AM9/2/93
to
dia...@jit.dec.com (Norman Diamond) writes:
|ANSI Classic section 4.8.1.2 (va_arg) page 123 lines 43 to 44: "The
|parameter ap shall be the same as the va_list ap initialized by va_start."
^^

|If two different va_list objects are initialized by two invocations of
|va_start, then the parameter ap cannot be the same as both of them.

By specifying the name, they're referring to the specific va_start on ap
(as opposed to, say, a va_start on va_list bp). If you drop the specific
name from the clause, then you get the single instance va_start.
--
David Tanguay d...@Thinkage.on.ca d...@Thinkage.com uunet!thinkage!dat
Thinkage, Ltd. Kitchener, Ontario, Canada [43.40N 80.47W]

Sammy D.

unread,
Sep 4, 1993, 1:52:51 PM9/4/93
to
In article <CCC0t...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>There's no wording in the standard to forbid it, and I can't see any
>reason, offhand, why it shouldn't be possible. The only arguments I've
>ever heard on this turn out to be easily demolished (they tend to assume
>things like va_start containing an unbalanced { matched by a } in
>va_end, which it is easy to prove is not a conforming implementation).

I don't have my copy of the standard handy, but I was under the
impression that the defs for va_start and va_end were deliberatly
designed so that the implementor could legally use a { in one and the
matching } in the other.

Clive Feather

unread,
Sep 6, 1993, 3:14:53 AM9/6/93
to
In article <1993Sep4.1...@wuecl.wustl.edu> jl...@cec2.wustl.edu (Sammy D.) writes:
> I don't have my copy of the standard handy, but I was under the
> impression that the defs for va_start and va_end were deliberatly
> designed so that the implementor could legally use a { in one and the
> matching } in the other.

There is *definitely* no wording requiring va_start and va_end to be
invoked at the same lexical scope, so I don't think that is correct.

Karl Heuer

unread,
Sep 7, 1993, 11:50:32 AM9/7/93
to
In article <CCx84...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>In article <1993Sep4.1...@wuecl.wustl.edu> jl...@cec2.wustl.edu (Sammy D.) writes:
>> I don't have my copy of the standard handy, but I was under the
>> impression that the defs for va_start and va_end were deliberatly
>> designed so that the implementor could legally use a { in one and the
>> matching } in the other.
>
>There is *definitely* no wording requiring va_start and va_end to be
>invoked at the same lexical scope, so I don't think that is correct.

I believe that what Sammy D. is thinking of is that there were historical
implementations of <varargs.h> which did use mismatched braces. However, the
Committee decided that it was the responsibility of the implementation to make
<stdarg.h> work correctly without such lexical kludges.

Ronald F. Guilmette

unread,
Sep 9, 1993, 6:50:35 AM9/9/93
to
In article <CCx84...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
>In article <1993Sep4.1...@wuecl.wustl.edu> jl...@cec2.wustl.edu (Sammy D.) writes:
>> I don't have my copy of the standard handy, but I was under the
>> impression that the defs for va_start and va_end were deliberatly
>> designed so that the implementor could legally use a { in one and the
>> matching } in the other.
>
>There is *definitely* no wording requiring va_start and va_end to be
>invoked at the same lexical scope, so I don't think that is correct.

I'm not sure his question even related to that point anyway. Consider:

#define va_start() {
#define va_end() }

void foobar ()
{
{
va_start()
}
va_end()
}

I think that still parses OK.

Joerg Czeranski

unread,
Sep 9, 1993, 9:01:35 PM9/9/93
to
Ronald F. Guilmette (r...@netcom.com) wrote:
: In article <CCx84...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
: >There is *definitely* no wording requiring va_start and va_end to be

: >invoked at the same lexical scope, so I don't think that is correct.
:
: I'm not sure his question even related to that point anyway. Consider:
:
: #define va_start() {
: #define va_end() }
:
: void foobar ()
: {
: {
: va_start()
: }
: va_end()
: }
:
: I think that still parses OK.

But shouldn't one expect, that the following works:

void foo()
{
va_start();
...
if (...)
{
va_end();
return;
}
...
va_end();
}

In this situation { and } need to be balanced.

joerg

--
Joerg Czeranski EMail czer...@rz.tu-clausthal.de
Osteroeder Strasse 55 SMTP injc@[139.174.2.10]
D38678 Clausthal-Zellerfeld Voice (at work) +49-5323-72-3896
Germany Voice (at home) +49-5323-78858

To obtain PGP public key, finger in...@sun.rz.tu-clausthal.de, or email me.

At any given site for any given application or feature, there's someone
who knows more about it than the support staff. Finding that person is
the first step to take to diagnose any given problem.

Christopher R. Volpe

unread,
Sep 10, 1993, 9:18:52 AM9/10/93
to
In article <rfgCD3...@netcom.com>, r...@netcom.com (Ronald F. Guilmette) writes:
|> In article <CCx84...@x.co.uk> cl...@x.co.uk (Clive Feather) writes:
|> >In article <1993Sep4.1...@wuecl.wustl.edu> jl...@cec2.wustl.edu (Sammy D.) writes:
|> >> I don't have my copy of the standard handy, but I was under the
|> >> impression that the defs for va_start and va_end were deliberatly
|> >> designed so that the implementor could legally use a { in one and the
|> >> matching } in the other.
|> >
|> >There is *definitely* no wording requiring va_start and va_end to be
|> >invoked at the same lexical scope, so I don't think that is correct.
|>
|> I'm not sure his question even related to that point anyway. Consider:
|>
|> #define va_start() {
|> #define va_end() }
|>
|> void foobar ()
|> {
|> {
|> va_start()
|> }
|> va_end()
|> }
|>
|> I think that still parses OK.

Yeah, but it would definitely change the meaning of the following:


void foobar ()
{
int i=2;
{
int i=4;
va_start()
}
if (i!=2) printf("Unexpected scope behavior!\n");
va_end()
}

|>
|> --
|>
|> -- Ronald F. Guilmette ------------------------------------------------------
|> ------ domain address: r...@netcom.com ---------------------------------------
|> ------ uucp address: ...!uunet!netcom.com!rfg -------------------------------

--

Chris Volpe
G.E. Corporate R&D
vol...@crd.ge.com

0 new messages