Re: patch: garbage error strings in libpq

From: jtv(at)xs4all(dot)nl
To: "Neil Conway" <neilc(at)samurai(dot)com>
Cc: jtv(at)xs4all(dot)nl, "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-patches(at)postgresql(dot)org
Subject: Re: patch: garbage error strings in libpq
Date: 2005-07-06 10:35:47
Message-ID: 22835.202.47.227.25.1120646147.squirrel@202.47.227.25
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches

Neil Conway wrote:
> The text is the same in both versions:
>
> http://dev.unicals.com/papers/c89-draft.html#3.3.2.2
>
> "The order of evaluation of the function designator, the arguments, and
> subexpressions within the arguments is unspecified, but there is a
> sequence point before the actual call."
>
> (On reading this more closely, I suppose you could make the argument
> that a function call that takes place in the argument list of another
> function call is a "subexpression within the [outer function's]
> arguments", so the order of evaluation prior to the call of the outer
> function would be undefined. But I don't think that's the right reading
> of the standard.)

That is pretty much what I remember hearing at the time.

To me what this says is only that (the program will behave as if) all
arguments shall be evaluated before the function is called--but in an
otherwise unspecified order. What we're currently doing has this basic
shape:

int x = 0;
static int a() { x = 1; return x; }
static int b() { printf("b sees x=%d\n", x); return x;}
static int c(int l, int r) { printf("c sees x=%d\n", x); return x; }
int main()
{
return c(a(),b());
}

Now, the best we can hope for based on what you quote is that we will see
"c sees x=1" but we don't know what we'll see coming out of b(). And the
wording makes it equally clear that we would not change any of this by
doing c(b(),a()) instead of c(a(),b()).

The "best we can hope for" depends on the definition of "unspecified."
This is where it gets really tricky. I see two different possible
implications depending on that definition:

(optimistic) The program will execute as if the code said either "t1=a();
t2=b(); c(t1,t2)" or "t1=b(); t2=a(); c(t1,t2)" but we don't know which.
I wouldn't bet on this one as a guarantee, although naive compilers will
probably behave like this.

(pessimistic) The executions of a() and b() may be interspersed freely,
although as a practical matter the compiler will respect the sequence
points within each. But that still means there is no sequence point
between any one given expression in the execution of a() and any other in
the execution of b(), therefore setting a variable in a() and also
touching it in b() leaves behaviour undefined. The program may react in
any way it likes without violating the standard, including traveling back
in time and refusing to start at all (really!), going off to make tea, or
standing on its head and donning a tutu.

A well-known way to trigger undefined behaviour is "x++=x++;" because
there is no sequence point between the two side effects. Try it: gcc will
give you a stern warning. Given that there is no sequence point between
argument expressions, as per the paragraph you quote, the same must go for
"c(x++,x++)". So then it becomes dubious that there is suddenly a
guarantee for "c(a(),b())"!

Jeroen

In response to

Responses

Browse pgsql-patches by date

  From Date Subject
Next Message Neil Conway 2005-07-06 12:37:04 Re: patch: garbage error strings in libpq
Previous Message Dave Page 2005-07-06 10:07:01 Re: [HACKERS] Dbsize backend integration