tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: why cast to char* through void*



On Sat, Jul 04, 2009 at 02:13:06PM -0400, Greg A. Woods wrote:
 > > > Well, yes, but that's where I'm trying to say it is appropriate to use
 > > > /*LINTED*/ comments.  These kinds of pointer aliasing tricks are indeed
 > > > sometimes necessary, 
 > > 
 > > No amount of LINTED will prevent demons from flying out of your nose
 > > if you do something that isn't defined. That's the concern.
 > 
 > Indeed -- but the "undefined" behaviour you speak of, I think, is the
 > very strict and narrow meaning given by the C Standard.

Well yes, but that's what defines the language after all.

 > The purpose of using LINTED to mark section of code that exploits a
 > "strictly undefined" behaviour (i.e. and not changing that code to avoid
 > the problem in the first place) is to say that we know what's happening
 > here and we're pretty sure the implementation we're using, and/or the
 > environments we've prepared the code to be used in, will not cause any
 > demons to fly out of anywhere, but if someone else moves this code to
 > another platform they should carefully check the marked code to be sure
 > it doesn't need changing to avoid demons in the new environment.

Yes; the problem is that things we think may be defined by the
platform (because of the function call ABI or characteristics of the
CPU or whatever) are, in fact, not, and fail silently with the next
compiler release. This has happened before with gcc and will doubtless
happen again.

This area is, IME, where most arguments about C and the C standard
arise: we know what happens on our CPUs when signed integer arithmetic
overflows, so we expect to be able to access that behavior by doing
computations on "int". Only, because it's still not actually defined,
the compiler is free to cause something else to happen, and sometimes
for one reason or another it will. And thus you get the spectacle of

   int x = ...
   int y = ...

   assert(x > 0);
   assert(y > 0);
   z = x+y;
   assert(z > 0);
   return z;

yielding a negative number without asserting. Whether this is
desirable behavior in a compiler is debatable, but it *is* legal
behavior.

With strict-aliasing the causes and symptoms of nasal demons are
typically much more subtle but the same risks occur -- possibly bigger
risks precisely because of that subtlety.

 > Indeed that's also probably the real reason why lint and gcc are giving
 > different warnings here -- lint is sticking closer to the "strictly
 > undefined" side of the fence, and gcc (being the actual implementation)
 > is saying that the cast through (char*) is OK because it will do what's
 > expected here (i.e. this implementation has a well defined behaviour).

Well, maybe it does. Is this behavior documented? Is it something the
gcc folks expect/intend to support down the road? My guess is that it
isn't.

 > Lint(1) should probably have an option to ignore LINTED comments though
 > to aid those preparing a port to another environment.  Perhaps '-p'
 > should do that by default.
 > 
 > Dumbing down lint, and/or making it specific to only one dialect and/or
 > implementation, would be a bad thing.

lint should be made smarter so as to require less LINTED markup.

-- 
David A. Holland
dholland%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index