This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: patches for Irix binutils 2.18 -- removal of some casts


On Thu, 23 Oct 2008, Alan Modra wrote:

On Wed, Oct 22, 2008 at 11:48:10AM -0500, Michael Hennebry wrote:
On Wed, 22 Oct 2008, Alan Modra wrote:
void foo (int count, void **p)
{
 while (--count >= 0)
   {
     long *q = *(long **)(--p);
     *p = 0;
     printf ("%p\n", q);
   }
}

If you can't immediately spot the problem, you're not alone!

Not knowing what it is supposed to do doesn't help either.

Clear an array of pointers and print their previous values. At high optimisation levels with loop unrolling, gcc generated code that printed some zeros, even though the array was originally all non-zero. In other words, the "*p = 0" assignment occurred before q had been read for the corresponding array element. This is not a gcc bug since the above code has undefined behaviour according to the C standard.

With a correct cast, all should have been well in either C or C++. There might be a case in which I would convert void** to long**, but I can't think of any at the moment.

Supposing p is a pointer into an array of pointers
to void and the pointers to void point to longs:
The cast is unnecessary in C.

Yes.


In C++, a statement should be: long *q = (long*)*(--p);

Agreed, this is the correct cast, if you must have one.


In neither C nor C++ is a conversion from void**
to long** guaranteed to produce a valid result.
If void** and long** have different formats,
evil is pretty much guaranteed.
Is that what happened?

No, long** and void** had exactly the same representation. Still puzzled?

No you gave me the answer. The programmer used a wrong cast. It hadn't occurred to me that the compiler would use the undefinedness of a cast as an excuse to reorder code.

Was there a reason the programmer used pointer to long?
It seems to me that
void *q = *--p;
would have been correct, simpler and easier to think about.
If long* and void* have different formats,
printf is guaranteed to print long* incorrectly.

--
Michael   hennebry@web.cs.ndsu.NoDak.edu
"Pessimist: The glass is half empty.
Optimist:   The glass is half full.
Engineer:   The glass is twice as big as it needs to be."


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]