This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC 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: strict aliasing: how to swap pointers


Evan Jones wrote:
> On Apr 30, 2008, at 4:55 , Andrew Haley wrote:
>> We have no way to know, since you didn't provide us with the source of
>> exchange(), and that's where the aliasing violation, if any, would
>> occur.
> 
> Oops! Sorry, I meant to. The simplest implementation is a swap using a
> temporary:
> 
> void* exchange(void** ptr, void* next) {
>  void* old = *ptr;
>  *ptr = next;
>  return old;
> }

Ok, so you have an aliasing violation.

>> However, the answer is almost certainly no.  I don't know why you're
>> trying to do something so simple in such a difficult way.  If you really
>> want to do this in standard portable C, the easiest way is a macro:
> 
> I have implementations of exchange() that either use a temporary, a
> compare-and-swap, a load-linked/store-conditional, or a mutex. There is
> some project-specific configuration to link against the appropriate
> implementation.

OK, there is no way to do this in standard C.  

> On Apr 30, 2008, at 12:18, Sergei Organov wrote:
>> Now, here is a solution that does not break strict aliasing rules:
>>
>> $ cat alias.cc
>> #include <cstdio>
>> #include <cstring>
>>
>> using namespace std;
>>
>> void swap(void* p1, void* p2)
>> {
>>   void* t;
>>   memcpy(&t, p1, sizeof(t));
>>   memcpy(p1, p2, sizeof(t));
>>   memcpy(p2, &t, sizeof(t));
>> }
> 
> This seems reasonable. In my version, I would simply return t, rather
> than using the last memcpy.
> 
> What is confusing to me about the strict aliasing warning is that I
> thought GCC must conservatively assume that a void* pointer can point to
> anything, since T* is convertible to void*. Hence, it seems to me that
> casting a T** to void** should not result in a type-punning warning.

It will.

Consider an arch which has pointers to char (and void *) that are two words
in size, and pointers to int that are one word in size.  On such an arch
your exchange() function won't work, which is one reason why you need a macro
to do it in Standard C.

> Additionally I'm confused because the warning is quite "fragile." This
> causes the warning:
> 
> void** voidptrptr = reinterpret_cast<void**>(&intptr);
> 
> This does not:
> 
> int** intptrptr = &intptr;
> void** voidptrptr = reinterpret_cast<void**>(intptrptr);
> 
> To me, these appear to be equivalent.

Indeed.  It's a heuristic, and it doesn't see all cases of aliasing violations.

Andrew.


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