Subject: Re: port-xen/29887: sysctl kern.consdev coredumps
To: None <tech-userlevel@NetBSD.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-userlevel
Date: 06/19/2005 18:10:49
I've been thinking a bit more about this gcc change, and I think I may
have a better handle on why it bothers me to the point that I called it
a bug.  This seems like a good place in the discussion to explain.

> i.e. a future gcc change that breaks this would be break it by
> demonstrating a place where we should have been printing "(null)"
> anyhow.

Except that it might not be a place where *we* have the choice.  For
example, gcc would be equally within its rights to generate an inline
dereference of the first byte of the string, which could core without
giving us any chance to catch it.  (Why it would want to is an open
question.  A possibility might be that profiling showed enough
zero-length strings being passed to make it worth optimizing away the
call overhead.)

That's why I called the printf->fputs change a bug, and more generally
this kind of "we're going to use all the license we can possibly find
in the standard to go hog-wild without caring what we do in cases that
are de jure undefined" thing.  We (NetBSD) extended the semantics of
printf() slightly, by making it print (null) for string conversions of
nil pointers - not incompatible with the standard, since the standard
specifies that behaviour is undefined in that case, but promising more
than the standard requires.

Then gcc, which didn't know we had this extension, decided that certain
printf calls were equivalent to certian other fputs calls.  This
equivalence holds in cases where the semantics are defined by the
standard, but not necessarily in other cases.  The coredump that
started this thread off arose because that equivalence did not hold a
particular case where the standard does not specify the behaviour, but
we historically did.

And I think that is what bothers me about what gcc did: they assumed,
incorrectly in our case, that the semantics of cases not defined by the
standard didn't matter, so they could make a certain transformation
without caring what happened in cases the standard didn't define.

Abstractly, the same thing is true of inlining bcopy (a transformation
with which this one was compared upthread).  As I see it, they were
just as abstractly wrong there; they got away with it in practice
because the historical behaviour matched the behaviour of the
transformed version closely enough.  (Core dumps are core dumps; the
major difference is that a frame is missing from the call stack, but
apparently that bothers few enough people to not matter.)

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B