public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Re: Weird strict-aliasing break
@ 2011-05-30 13:08 Thibault Castel
  2011-05-30 18:47 ` Andrew Haley
  0 siblings, 1 reply; 7+ messages in thread
From: Thibault Castel @ 2011-05-30 13:08 UTC (permalink / raw)
  To: gcc-help; +Cc: steffen.dettmer

> ---------- Message transféré ----------
> From: Steffen Dettmer <steffen.dettmer@googlemail.com>
> To: gcc-help@gcc.gnu.org
> Date: Mon, 30 May 2011 13:59:51 +0200
> Subject: Re: Weird strict-aliasing break
> On Mon, May 30, 2011 Thibault Castel <thibault.castel@gmail.com> wrote:
>> I have a weird warning when compiling my program with g++:
>>   "dereferencing pointer ‘NAME’ does break strict-aliasing rules"
>>
>> So, I tried to investigate a little bit and find some clues : I do a
>> memory mapping from a char buffer to a C struct to have access to
>> different datas into the buffer. Pretty casual. But, when I try to
>> access one of my inner field, the warning triggers... Huh...
>
> Beside that this may have other disadvantages, such as depending
> on byte order, padding and alighnment issues, in general you
> cannot assume that constructions like:
>
> struct s {
>   int a; // or int32_t
> };
> char buffer[];
>
> struct s *p = buffer;   p->a;
> struct s *p = buffer+1; p->a;
>
> this even may crash (we had such problems on some ARM CPUs).
>

Yes, we have some ARM CPUs as targets but specific code (with such
aligment adaptations) are used. The code I provided is x86 targeted
only ;)

> I think better here is using memcpy, but still "you have to know
> what you are doing".

No, because I don't want to copy anything. I just need to access
fields for reading and extracting data. I don't write into it. It's
really just a memory mapping.

>
> I think the only 100% correct way is proper deserialisation, maybe this way:
>
> struct s *p = new struct s;
> p->a =
>      (int)(buffer[0]) * 0x1000000 +
>      (int)(buffer[1]) * 0x0010000 +
>      (int)(buffer[2]) * 0x0000100 +
>      (int)(buffer[3]);
>
> A better workaround for the alignment probably could be something like:
>
> struct s {
>   int a; // or int32_t
> };
> char buffer[];
>
> union x {
>    struct s;
>    char buffer[1];
> }
>
>> I successfully avoid the warning with "__attribute__((__may_alias__))"
>> but this "cheat" bother me because :
> - you might have a case where it breaks things
>  (such as optimization changes behavior)
>
> I hope some expert corrects me where I'm wrong.

I don't like this directive. If I can avoid it, it would be great.

>
> oki,
>
> Steffen

Thanks

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Weird strict-aliasing break
  2011-05-30 13:08 Re: Weird strict-aliasing break Thibault Castel
@ 2011-05-30 18:47 ` Andrew Haley
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Haley @ 2011-05-30 18:47 UTC (permalink / raw)
  To: gcc-help

On 05/30/2011 01:33 PM, Thibault Castel wrote:
>> ---------- Message transféré ----------
>> From: Steffen Dettmer <steffen.dettmer@googlemail.com>
>> To: gcc-help@gcc.gnu.org
>> Date: Mon, 30 May 2011 13:59:51 +0200
>> Subject: Re: Weird strict-aliasing break
>> On Mon, May 30, 2011 Thibault Castel <thibault.castel@gmail.com> wrote:
>>> I have a weird warning when compiling my program with g++:
>>>   "dereferencing pointer ‘NAME’ does break strict-aliasing rules"
>>>
>>> So, I tried to investigate a little bit and find some clues : I do a
>>> memory mapping from a char buffer to a C struct to have access to
>>> different datas into the buffer. Pretty casual. But, when I try to
>>> access one of my inner field, the warning triggers... Huh...
>>
>> Beside that this may have other disadvantages, such as depending
>> on byte order, padding and alighnment issues, in general you
>> cannot assume that constructions like:
>>
>> struct s {
>>   int a; // or int32_t
>> };
>> char buffer[];
>>
>> struct s *p = buffer;   p->a;
>> struct s *p = buffer+1; p->a;
>>
>> this even may crash (we had such problems on some ARM CPUs).
>>
> 
> Yes, we have some ARM CPUs as targets but specific code (with such
> aligment adaptations) are used. The code I provided is x86 targeted
> only ;)
> 
>> I think better here is using memcpy, but still "you have to know
>> what you are doing".
> 
> No, because I don't want to copy anything. I just need to access
> fields for reading and extracting data. I don't write into it. It's
> really just a memory mapping.

You're still better off with memcpy.  There's no loss of efficiency,
and it'll be legal C++.

Andrew.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Weird strict-aliasing break
  2011-05-30 12:47 ` Sebastian Huber
@ 2011-05-30 19:12   ` Steffen Dettmer
  0 siblings, 0 replies; 7+ messages in thread
From: Steffen Dettmer @ 2011-05-30 19:12 UTC (permalink / raw)
  To: gcc-help

On Mon, May 30, 2011 at 2:25 PM, Sebastian Huber
<sebastian.huber@embedded-brains.de> wrote:
> you may have a look at:
>
> http://dbp-consulting.com/StrictAliasing.pdf
[Patrick Horgan's "Understanding C/C++ Strict Aliasing"]

Wow, what a nice document, it explains it well and easy to understand
and compares solutions, cool!

Thanks,
Steffen

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Weird strict-aliasing break
  2011-05-30 12:25 Thibault Castel
  2011-05-30 12:33 ` Axel Freyn
  2011-05-30 12:40 ` Steffen Dettmer
@ 2011-05-30 12:47 ` Sebastian Huber
  2011-05-30 19:12   ` Steffen Dettmer
  2 siblings, 1 reply; 7+ messages in thread
From: Sebastian Huber @ 2011-05-30 12:47 UTC (permalink / raw)
  To: gcc-help

Hi,

you may have a look at:

http://dbp-consulting.com/StrictAliasing.pdf

On 05/30/2011 10:34 AM, Thibault Castel wrote:
[...]
> int main (int ac, char** av)
> {
>   TData data;
>   char raw[10];

Character types can point to anything.  I am not sure if this also includes
char [].  Lets assume it does.

>   TDummy* pFoo = NULL;
>   char* pChar = NULL;
[...]
>   // No warning - Why ???
>   pFoo = (TDummy*) (raw);

Character types can point to anything.

[...]
>   // Strict aliasing warning - Why ???
>   pFoo = (TDummy*) (data.raw);

TDummy and TData are different types.  You can modify now a TData through a
TDummy pointer and this violates the strict aliasing rules.

-- 
Sebastian Huber, embedded brains GmbH

Address : Obere Lagerstr. 30, D-82178 Puchheim, Germany
Phone   : +49 89 18 90 80 79-6
Fax     : +49 89 18 90 80 79-9
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Weird strict-aliasing break
  2011-05-30 12:25 Thibault Castel
  2011-05-30 12:33 ` Axel Freyn
@ 2011-05-30 12:40 ` Steffen Dettmer
  2011-05-30 12:47 ` Sebastian Huber
  2 siblings, 0 replies; 7+ messages in thread
From: Steffen Dettmer @ 2011-05-30 12:40 UTC (permalink / raw)
  To: gcc-help

On Mon, May 30, 2011 Thibault Castel <thibault.castel@gmail.com> wrote:
> I have a weird warning when compiling my program with g++:
>   "dereferencing pointer ‘NAME’ does break strict-aliasing rules"
>
> So, I tried to investigate a little bit and find some clues : I do a
> memory mapping from a char buffer to a C struct to have access to
> different datas into the buffer. Pretty casual. But, when I try to
> access one of my inner field, the warning triggers... Huh...

Beside that this may have other disadvantages, such as depending
on byte order, padding and alighnment issues, in general you
cannot assume that constructions like:

struct s {
   int a; // or int32_t
};
char buffer[];

struct s *p = buffer;   p->a;
struct s *p = buffer+1; p->a;

this even may crash (we had such problems on some ARM CPUs).

I think better here is using memcpy, but still "you have to know
what you are doing".

I think the only 100% correct way is proper deserialisation, maybe this way:

struct s *p = new struct s;
p->a =
      (int)(buffer[0]) * 0x1000000 +
      (int)(buffer[1]) * 0x0010000 +
      (int)(buffer[2]) * 0x0000100 +
      (int)(buffer[3]);

A better workaround for the alignment probably could be something like:

struct s {
   int a; // or int32_t
};
char buffer[];

union x {
    struct s;
    char buffer[1];
}

> I successfully avoid the warning with "__attribute__((__may_alias__))"
> but this "cheat" bother me because :
- you might have a case where it breaks things
  (such as optimization changes behavior)

I hope some expert corrects me where I'm wrong.

oki,

Steffen

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Weird strict-aliasing break
  2011-05-30 12:25 Thibault Castel
@ 2011-05-30 12:33 ` Axel Freyn
  2011-05-30 12:40 ` Steffen Dettmer
  2011-05-30 12:47 ` Sebastian Huber
  2 siblings, 0 replies; 7+ messages in thread
From: Axel Freyn @ 2011-05-30 12:33 UTC (permalink / raw)
  To: gcc-help

Hi Thibault,

On Mon, May 30, 2011 at 10:34:40AM +0200, Thibault Castel wrote:
> Hi,
> 
> I have a weird warning when compiling my program with g++:
>    "dereferencing pointer ‘NAME’ does break strict-aliasing rules"
> 
> So, I tried to investigate a little bit and find some clues : I do a
> memory mapping from a char buffer to a C struct to have access to
> different datas into the buffer. Pretty casual. But, when I try to
> access one of my inner field, the warning triggers... Huh...
> 
> To understand a bit more, I wrote a litte test program outside of my
> project (really huge). See it in attachment. And I don't really
> understand, because the warning is triggered only line 77, not on line
> 55. Only when I try to access the inner fields of a mapped structured
> included into another structure.
> 
> I successfully avoid the warning with "__attribute__((__may_alias__))"
> but this "cheat" bother me because :
>  - I don't want to fake the compiler
>  - I need to compile my huge project both under Linux (gcc/g++) and
> Windows (Visual IDE)
>  - This warning is triggered a hundred times in my huge project (old C
> project slowly turning into C++ :/)
> 
> I already saw some messages on this list about this warning. But the
> difference here is my program IS working. pFoo->a and pFoo->b have
> correct values.
> 
> I tried different scenarios
>  - grow or reduce the raw array
>  - change the definition order into TData
> 
> [...]
>
> Thanks a lot for any clue or explanation

I'm not 100% sure -- however here is my opinion:

 - the strict aliasing rules assume that you never access an object
   through two pointers of different type "at the same time", so 
   your code in line 54 violates strict aliasing, too.

 - if you violate strict aliasing, that MIGHT introduce problems
   (especially during optimization, and if you change values). However,
   it might work without any problems.

 - gcc warns not about ALL, but only about SOME strict-aliasing
   violations. You can adjust the warnings by -Wstrict-aliasing=1 (or
   2 or 3). With "-Wstrict-aliasing=2", I also obtain the warning
warn-strict.cpp:54: warning: dereferencing type-punned pointer will break strict-aliasing rules
   I think, gcc tries to warn only when it "expects" problems. So
   probably gcc is "quite sure" that line 54 does not introduce
   problems (for example gcc 4.7 on x86_64 does not warn at all for
   your code).

 - you can avoid all problems with gcc by using "-fno-strict-aliasing",
   which tells gcc not to assume strict aliasing during it's
   optimizations: with this option, everything should be safe.

I don't know of any portable way how to avoid this possible problem (except
correcting the code...)


Axel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Weird strict-aliasing break
@ 2011-05-30 12:25 Thibault Castel
  2011-05-30 12:33 ` Axel Freyn
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Thibault Castel @ 2011-05-30 12:25 UTC (permalink / raw)
  To: gcc-help

[-- Attachment #1: Type: text/plain, Size: 2315 bytes --]

Hi,

I have a weird warning when compiling my program with g++:
   "dereferencing pointer ‘NAME’ does break strict-aliasing rules"

So, I tried to investigate a little bit and find some clues : I do a
memory mapping from a char buffer to a C struct to have access to
different datas into the buffer. Pretty casual. But, when I try to
access one of my inner field, the warning triggers... Huh...

To understand a bit more, I wrote a litte test program outside of my
project (really huge). See it in attachment. And I don't really
understand, because the warning is triggered only line 77, not on line
55. Only when I try to access the inner fields of a mapped structured
included into another structure.

I successfully avoid the warning with "__attribute__((__may_alias__))"
but this "cheat" bother me because :
 - I don't want to fake the compiler
 - I need to compile my huge project both under Linux (gcc/g++) and
Windows (Visual IDE)
 - This warning is triggered a hundred times in my huge project (old C
project slowly turning into C++ :/)

I already saw some messages on this list about this warning. But the
difference here is my program IS working. pFoo->a and pFoo->b have
correct values.

I tried different scenarios
 - grow or reduce the raw array
 - change the definition order into TData

My gcc specs :
=======================
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian
4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.4 --enable-shared --enable-multiarch
--enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib
--enable-nls --enable-clocale=gnu --enable-libstdcxx-debug
--enable-objc-gc --enable-targets=all --with-arch-32=i586
--with-tune=generic --enable-checking=release --build=i486-linux-gnu
--host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)
=========================

Thanks a lot for any clue or explanation

PS: I'm french, and don't really speak english. I already apologize for that :/

Thibault

[-- Attachment #2: warn-strict.cpp --]
[-- Type: text/x-c++src, Size: 1451 bytes --]

#include <stdlib.h>
#include <stdio.h>

typedef struct 
{
  unsigned char a;
  unsigned char b;
  unsigned char c;
} TDummy;
// } __attribute__((__may_alias__)) TDummy;

typedef struct
{
  unsigned char foo;
  unsigned char bar;
  char raw[10];
  unsigned char tmp;
  unsigned char pop;
} TData;

int main (int ac, char** av)
{
  TData data;
  char raw[10];
  TDummy* pFoo = NULL;
  char* pChar = NULL;

  // Init
  for (unsigned char i = 0; i < 10; ++i)
  {
    data.raw[i] = i;
    raw[i] = i;
  }

  // RAW ACCESS =================================================
  printf ("Raw   => ");
  for (unsigned char i = 0; i < 10; ++i)
  {
    printf ("%d", raw[i]);
    if (i != 9)
      printf (",");
  }
  printf ("\n");
      
  // No warning
  pChar = raw;
  printf ("Void  => ");
  printf ("%d,", *(pChar));
  pChar++;
  printf ("%d\n", *(pChar));
  pChar++;

  // No warning - Why ???
  pFoo = (TDummy*) (raw);
  printf ("Dummy => %d,%d\n", pFoo->a, pFoo->b);

  // DATA ACCESS =================================================
  printf ("Data  => ");
  for (unsigned char i = 0; i < 10; ++i)
  {
    printf ("%d", data.raw[i]);
    if (i != 9)
      printf (",");
  }
  printf ("\n");

  // No warning
  pChar = data.raw;
  printf ("Void  => ");
  printf ("%d,", *(pChar));
  pChar++;
  printf ("%d\n", *(pChar));
  pChar++;

  // Strict aliasing warning - Why ???
  pFoo = (TDummy*) (data.raw);
  printf ("Dummy => %d,%d\n", pFoo->a, pFoo->b);
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-05-30 16:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-30 13:08 Re: Weird strict-aliasing break Thibault Castel
2011-05-30 18:47 ` Andrew Haley
  -- strict thread matches above, loose matches on Subject: below --
2011-05-30 12:25 Thibault Castel
2011-05-30 12:33 ` Axel Freyn
2011-05-30 12:40 ` Steffen Dettmer
2011-05-30 12:47 ` Sebastian Huber
2011-05-30 19:12   ` Steffen Dettmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).