locked
BUG report (C, unnamed unions) RRS feed

  • General discussion

  • Please compile the code below, and open the generated *.COD file.

    This is what I get:

    _Y0 DD  020001H
        DD  040003H

    _Y1 DD  00H      < and here is the error, it should be 020001H, the same as Y0
        DD  040003H

    Now, please comment the last two lines, compile and Y0 and Y1 will be the same (as they should be).
    Uncomment the last two lines.

    In the UN1 union, move a3 to top, compile and Y0/Y1 will exchange:
    _Y0 DD  00H
        DD  040003H

    _Y1 DD  020001H
        DD  040003H

    Hopefully this will be fixed.

    typedef union {
    //  unsigned int a3;      // uncomment this one, and comment...
      struct {
        unsigned int a1:16;
        unsigned int a2:16;
      };
      unsigned int a3;        // .... this one
    } UN1;
    
    typedef union {
      struct {
        UN1 b1;
        UN1 b2;
      };
    } UN2;
    
    typedef struct {
      UN2 c3;
    } STR;
    
    STR Y0 = {
      .c3.b1.a1 = 1,
      .c3.b1.a2 = 2,
    
      .c3.b2.a1 = 3,
      .c3.b2.a2 = 4
    };
    
    STR Y1 = {
      .c3.b1.a3 = 0x00020001, // this should be the same as initializing a1 and a2
    
      .c3.b2.a1 = 3,  // comment these two lines and it will work
      .c3.b2.a2 = 4
    };
    



    Thursday, June 30, 2016 5:50 PM

All replies

  • I've read somewhere that MS C compiler has problems with unnamed unions, that's why I've wrote "unnamed" in subject.
    But I've named them now, by adding "q" and it behaves the same.

    typedef union {
    //  unsigned int a3;      // uncomment this one, comment...
      struct {
        unsigned int a1:16;
        unsigned int a2:16;
      }q;
    
      unsigned int a3;        // .... this one
    } UN1;
    
    typedef union {
      struct {
        UN1 b1;
        UN1 b2;
      }q;
    } UN2;
    
    typedef struct {
      UN2 c3;
    } STR;
    
    STR Y0 = {
      .c3.q.b1.q.a1 = 1,
      .c3.q.b1.q.a2 = 2,
    
      .c3.q.b2.q.a1 = 3,
      .c3.q.b2.q.a2 = 4
    };
    
    STR Y1 = {
      .c3.q.b1.a3 = 0x00020001, // this should be the same as initializing a1 and a2
    
      .c3.q.b2.q.a1 = 3,  // comment these two lines and it will work
      .c3.q.b2.q.a2 = 4
    };



    • Edited by aleksazr2 Friday, July 1, 2016 8:29 AM
    Friday, July 1, 2016 8:17 AM
  • Hi aleksazr2,

    changing your code to explizit initialization works fine in VS2010:

    STR Y0;
    memset(&Y0, 0, sizeof(STR));
    Y0.c3.q.b1.q.a1 = 1;
    Y0.c3.q.b1.q.a2 = 2;
    
    Y0.c3.q.b2.q.a1 = 3;
    Y0.c3.q.b2.q.a2 = 4;		
    
    STR Y1;
    memset(&Y1, 0, sizeof(STR));
    Y1.c3.q.b1.a3 = 0x00020001; 
    _ASSERTE(Y1.c3.q.b1.q.a1 == 1);
    _ASSERTE(Y1.c3.q.b1.q.a2 == 2);
    Y1.c3.q.b2.q.a1 = 3;
    Y1.c3.q.b2.q.a2 = 4;


    Friday, July 1, 2016 9:17 AM
  • Thanks, but it also generates code, which in my real code wouldn't work because:
    a. Y0/Y1 are defined as CONST (need them in a read-only segment)
    b. Y0/Y1 are actually arrays.

    Friday, July 1, 2016 11:05 AM
  • I have noticed what I think is a bug as well with an unnamed struct within a named union.

    The union is defined as follows.

    union RandomData { unsigned long long Seed; struct { unsigned long Low; unsigned long High; }; }; // with the class below using the following algorithm // borrowed from http://www.geocities.ws/hmaxf_urlcr/rng.htm class CRandom { public: virtual void Seed(unsigned long dwSeedValue) { m_udtData.Seed ^= dwSeedValue; m_udtData.High ^= m_udtData.Low; m_udtData.Seed *= m_udtData.Seed; } virtual unsigned long Next32() { if ( !(m_udtData.Low & 0xC0000000) ) { Seed(time(NULL)); } m_udtData.Low ^= m_udtData.High; m_udtData.Seed *= m_udtData.Low; m_udtData.Seed <<= ( (m_udtData.Low % 3) + 4 ); if (m_udtData.High == 0) { time(NULL); }

    return m_udtData.High; } protected: RandomData m_udtData; };


    The code worked fine in previous versions of Visual Studio on a 32-bit processor, but I get different results and the numbers ARE NOT very random (I know it's pseudo random, but you know what I mean). This was a VERY GOOD RNG on previous versions of Visual C++ on 32-bit processors, but when I run this code on a 64-bit processor but in a Win32 (x86) app... Then the code isn't working properly. I think it's a bug with the compiler with regards to code generation.


    • Edited by Dynefire Sunday, July 3, 2016 9:59 AM forgot return value
    Sunday, July 3, 2016 9:34 AM
  • If you think this is a bug - would the MS CSG folks here be so kind and help the OP to send a bug report?

    Thanks,

    - pa

    Sunday, July 3, 2016 12:49 PM
  • On 7/3/2016 5:34 AM, Dynefire wrote:

    public:
        virtual void Seed(unsigned long dwSeedValue)
        {
            m_udtData.Seed ^= dwSeedValue;

            m_udtData.High ^= m_udtData.Low;

    Not sure about C (not as familiar with the C standard), but in C++, this exhibits undefined behavior, by way of accessing a member of the union other than the one that was last assigned (aka "type punning").

    The code worked fine in previous versions of Visual Studio on a 32-bit processor, but I get different results and the numbers ARE NOT very random (I know it's pseudo random, but you know what I mean). This was a VERY GOOD RNG on previous versions of Visual C++ on 32-bit processors, but when I run this code on a 64-bit processor but in a Win32 (x86) app... Then the code isn't working properly. I think it's a bug with the compiler with regards to code generation.

    This should be easy to demonstrate. There should be a seed value such that a sequence "rnd.Seed(thisSeed); auto n = rnd.Next32()" would return different results (without hitting the non-deterministic re-seeding in Next32, of course). Can you find such a seed? Then it would be easy to trace into implementation to see exactly where it goes wrong.

    Sunday, July 3, 2016 12:49 PM
  • If you think this is a bug - would the MS CSG folks here be so kind and help the OP to send a bug report?

    Thanks,

    - pa

    Like this?
    https://connect.microsoft.com/VisualStudio/feedback/details/2884610

    I've tried attaching the .c file, but C is not on the list of supported file extensions (CPP is, but this is a C file)

    Sunday, July 3, 2016 1:12 PM

  • Like this?
    https://connect.microsoft.com/VisualStudio/feedback/details/2884610

    Exactly. Maybe, emphasize the impact and mention that it worked in a previous version (which?)


    I've tried attaching the .c file, but C is not on the list of supported file extensions (CPP is, but this is a C file)

    @Igor, so this is in plain C mode.

    /* If memory serves, another "type punning" issue was discussed here recently.  IIRC it was agreed that c++ compiler shouldn't break legacy C behavior just for sake of being modern...*/

    -- pa

    Sunday, July 3, 2016 1:25 PM
  • https://connect.microsoft.com/VisualStudio/feedback/details/2884610

    Someone deleted the bug report, I get a "page not found" error.
    It was marked as ACTIVE yesterday and is now gone. It probably hasn't been fixed.

    Thursday, July 7, 2016 5:14 PM