Re: GCC 4.8.4 4.9.2 nifti_swap_2bytes optimization bug

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

 



On 04/02/2015 02:13 AM, Andrew Haley wrote:
On 04/01/2015 07:15 PM, Martin Sebor wrote:
On 04/01/2015 08:49 AM, Andrew Haley wrote:
On 04/01/2015 03:36 PM, Andreas Schuh wrote:

I believe I have encountered a bug in the optimization at least in
versions 4.8.4 and 4.9.2. The problem is not present in version
4.6.3. The attached complete example code can be used to reproduce
the error (my system is Ubuntu 12.04). This code is crucial in
medical image processing where the NIfTI-1 file format is commonly
used. The respective function that is optimized incorrectly by most
recent C/C++ compilers of GCC was copied from the NIfTI-1 C library
and is used by many medical image processing tools. It is
responsible for swapping the bytes if necessary when the image data
was written on a system with differing endianness.

Sure, but it's not standard C.  You really don't need to alias a
struct of two bytes and a short, and these are not compatible types.
(I can give you chapter and verse of the C standard if you really want
it, but the rule is simple: don't expect a cast between pointers to
different types to work.  Doing so via a hidden void* doesn't help.)

The C requirement is that "An object shall have its stored value
accessed only by an lvalue expression of ... a character type."
The original program accesses the value object via the tb[ii].a
and tb[ii].b expressions, which are both unsigned char lvalues.
That the program derives those lvalues from pointers to some
other type (*) doesn't violate the aliasing rule.

[*] As if by:

      unsigned char *b0 = &((twobytes*)ar + ii)->a;
      unsigned char *b1 = &((twobytes*)ar + ii)->b;
      tt = *b0;
      *b0 = *b1;
      *b1 = tt;

This is a common misconception.

It's wrong because a->b is identical to (*(a)).b and a[i] is identical
to (*((a)+(i))) .

Therefore, in the section above, the expression

  &((twobytes*)ar + ii)->a

is the same as

  &(((twobytes*)ar)[ii].b)

Correct (with b replaced by a). This equivalence is also
why accessing the result doesn't violate the aliasing rules.


and the illegal access is more obvious.

For the aliasing rule to be violated the access (defined in
3.1, p1 as an action to read or modify an object) to the
object would need to be via an lvalue of a type other than
character or short (such as struct twobytes in the example
program). However, none of the relevant subexpressions above
(as stated in 6.6, p9, neither the [] subscripting expression
nor the -> or . member selection operators accesses an object).
The access is only performed by the assignment expression when
the object designated by its right operand is read. The right
operand is, in all cases, an lvalue of character type.

Martin




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux