Re: sequence points and evaluation order



ena8t8si@xxxxxxxxx wrote:
Robert Gamble wrote:
Keith Thompson wrote:
Flash Gordon <spam@xxxxxxxxxxxxxxxxxx> writes:
Spiros Bousbouras wrote:
John Smith wrote:

I've been playing with splint, which returns the following
warning for the code below:

statlib.c: (in function log_norm_pdf)
statlib.c(1054,31): Expression has undefined behavior (left
operand uses errno,
modified by right operand): (log(x) - mu) * (log(x) - mu)
Code has unspecified behavior. Order of evaluation of function
parameters or
subexpressions is not defined, so if a value is used and
modified in
different places not separated by a sequence point
constraining evaluation
order, then the result of the expression is unspecified.
I'm a bit puzzled by this.
Is it unspecified or undefined ? And why is it either ?
When it says "operand uses errno" does it mean reads
the value of errno or it means reads or writes the value
of errno ?

The order of the two function calls is unspecified, but IIRC there is
a sequence point on calling a function, and the two calls are not
permitted to be run in parallel, so I can't see any undefined
behaviour. If either call sets errno it is guaranteed that errno will
be set to a non-0 value (standard functions do not set it to 0) so the
code can still test errno to see if an error has occurred and what at
least one error was. So I really don't see a problem.
[...]

If log() is implemented as a macro, there may not be a sequence point.

This is true, although it would be quite difficult to imagine a macro
version that calculates the log and sets errno all without introducing
a sequence point.

Despite the evidence of the error message above? That
makes it pretty easy to imagine I would say.

It's not too difficult to imagine *a* function that would do this as
virtually any library function may set errno, but it would be difficult
to imagine a conforming implementation of the log function that does as
its implementation is non-trivial and it returns a non-int value.

In any case, it is definitely a QOI issue although I
find it somewhat disturbing that the Standard allows this. I wonder
why the Standard committee didn't stick in something that prohibits the
modification of an object with static duration from a macro version of
a library function without appropriate sequence points.

Better still, a requirement that a macro version behave
as if the actual function would.

There is a sequence point before any function in C returns. Requiring
that all macro versions of library functions have this sequence point
would unnecessarily complicate and invalidate many existing macros
such as those covering functions in ctype.h. As long as the macro does
not modify objects with static duration I don't see a need for forcing
the macro version to implement the sequence point.

Robert Gamble

.



Relevant Pages

  • Re: Cleanup patterns
    ... In particular, if the function opens a number of resources, these need ... which uses the global errno to store ... them (macro ... set error code to success right before the cleanup ...
    (comp.lang.c)
  • Re: declaring errno
    ... > I see in the standard that errno may be a macro, ... > definition since it doesn't reserve storage. ... Each identifier with file scope listed in any of the following ...
    (comp.lang.c)
  • Re: sequence points and evaluation order
    ... When it says "operand uses errno" does it mean reads ... a sequence point on calling a function, and the two calls are not ... If either call sets errno it is guaranteed that errno will ...
    (comp.lang.c)
  • Re: Changes to stdlib.h from ver. 6.0 to ver. 8.0
    ... typedef struct TSK_Obj { ... "errno" is a macro that expands to a function call. ... shouldn't have used the name "errno" in the first place. ... order to access an actual object, or a program defines an identifier ...
    (microsoft.public.vc.language)
  • Re: detecting symbolic links in c
    ... How do you know errno can never be ... > a macro encapsulating a function? ... So, I guess it is not a good idea for me to declare it, after all. ... And of course, "extern int errno" is not technically a definition, so it ...
    (comp.unix.programmer)