Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #6228
| From | Vaclav Haisman <v.haisman@sh.cvut.cz> |
|---|---|
| Newsgroups | comp.lang.c++ |
| Subject | Re: unions |
| Date | 2011-06-05 07:29 +0200 |
| Organization | Czech Technical University |
| Message-ID | <4DEB141E.7060402@sh.cvut.cz> (permalink) |
| References | <iscfn1$keo$8@reader1.panix.com> <isdrr3$urc$1@node2.news.atman.pl> <4DEA75DF.6010402@sh.cvut.cz> <ise4sq$8e7$1@node2.news.atman.pl> |
Edek wrote, On 4.6.2011 22:34:
> On 06/04/2011 08:13 PM, Vaclav Haisman wrote:
>> Edek wrote, On 4.6.2011 19:59:
>>> Am I missing something about them? I
>>>> started to have deep doubts about what I thought I knew.
>>>>
>>>
>>> Other things aside, by the standard unions are the only
>>> possibility to alias two non-char types without breaking
>>> optimisations. Maybe void* is another and a couple of
>>> other strange cases. Don't ask me about where it is in the
>>> standard; I just know that it is a pain to find bugs
>>> caused by wrong casting coupled with unpredictable optimisation
>>> results (UB caused by casts really, unions are safe).
>> Unions are not safe. You cannot write using one union member and read using
>> another. It is only GCC extension that it works but the standard does not
>> allow it, AFAIK.
>>
>
> I think it here depends what is precisely meant. Code:
>
> typedef union {
> short _s;
> UU* _ptr;
> } UU;
>
> 1) Safe:
>
> short ok(UU *p1, UU* p2)
> {
> short tmp = p2->_s; // a
> p1->_ptr = p2; // b, by different type
>
>
> return tmp + p1->_ptr->_s; //c
>
> // I think this is what I meant as legal
> // all access by union
> // compiler knows a),b),c) may alias, same type accessed (UU)
> // which causes a reread of p2->_s at c), because it may have
> // been overwritten by b). No warnings.
>
> movzwl (%rsi), %eax a)
> movq %rsi, (%rdi) b)
> addw (%rsi), %ax c) <--- reload of _s
> ret
> // Note: no reordering either, in case rdi == rsi
> }
>
> 2) Also safe
>
> short alsoOk (UU* p1)
> {
> UU u; // not an aliasing problem, local copy accessed
> u._ptr = p1[23]->_ptr;
> return u._s;
This is not fine. The _s member has not been written to.
>
> movq 184(%rdi), %rax // Trivial
> ret
>
> };
>
> 3)
>
> short foo (UU *uu, int *p2)
> {
> // not allowed. Casting to union in main (below) does not mean
> // the same as my above 'all access by union'
>
> short tmp = uu->_s;
>
> p2[42] = 0; // may overwrite uu->_s
>
> return tmp + uu->_s; // will compiler reread uu->_s? No...
>
> movzwl (%rdi), %eax
> movl $0, 168(%rsi)
> addl %eax, %eax // tmp + tmp really
>
> }
>
> The output of the below is:
> $ ./main
> Is 84
> should be: 42
> $
>
>
> #include <iostream>
>
> using namespace std;
>
> extern short foo (UU*,int*);
>
> int main ()
> {
> int * ints = new int[100];
>
> for (int i = 0; i < 100; i++) ints[i]=i;
>
> int& ourVal = ints[42];
>
> short shouldBe = ((UU*)&ourVal)->_s; // warns
>
> cout << "Is " << foo ((UU*)&ourVal, ints) // warns
> << endl;
>
> shouldBe += ((UU*)&ourVal)->_s; // warns
>
> cout << " should be: " << shouldBe << endl;
>
> delete [] ints;
> return -1;
> }
>
>
>
> Is the extension you are referring to calling foo when UU is
>
> typedef union uu {
> short _s;
> union uu _ptr;
> int _int;
> };
>
> ? Then generated code is fine.
>
> Correct? I'm not a language lawyer. BTW, the effect depends on whether
> foo and main are compiled together or separately, and whether they are
> compiled with -fPIC or not, and possibly other options.
Incorrect, IMHO. When your code has UB it is broken. It might seem ok at
first or second glance but it is still broken. It might visibly break with
different compiler version, flags or platform.
--
VH
Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
unions Ruben Safir <ruben@mrbrklyn.com> - 2011-06-04 05:26 +0000
Re: unions Ian Collins <ian-news@hotmail.com> - 2011-06-04 17:38 +1200
Re: unions Ruben Safir <ruben@mrbrklyn.com> - 2011-06-04 05:45 +0000
Re: unions Ian Collins <ian-news@hotmail.com> - 2011-06-04 18:04 +1200
Re: unions Ruben Safir <ruben@mrbrklyn.com> - 2011-06-04 06:13 +0000
Re: unions Öö Tiib <ootiib@hot.ee> - 2011-06-04 04:54 -0700
Re: unions Edek <edek.pienkowski@gmail.com> - 2011-06-04 19:59 +0200
Re: unions Vaclav Haisman <v.haisman@sh.cvut.cz> - 2011-06-04 20:13 +0200
Re: unions Edek <edek.pienkowski@gmail.com> - 2011-06-04 22:34 +0200
Re: unions Vaclav Haisman <v.haisman@sh.cvut.cz> - 2011-06-05 07:29 +0200
Re: unions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-06-09 09:19 +0000
Re: unions Keith <kbelder@gmail.com> - 2011-06-09 11:17 -0700
Re: unions Victor Bazarov <v.bazarov@comcast.invalid> - 2011-06-09 14:29 -0400
Re: unions Edek <edek.pienkowski@gmail.com> - 2011-06-10 13:16 +0200
csiph-web