wrong size union - struct defining it with {}

hello,

i'am working with e2 studio, CC-RX project in C++ , cpu RX62T, toolchain 2.08. boundary alignment value for structure member is 1.

i have this structure: 

typedef union {
unsigned long U_LONG;
unsigned char BYTE[4]; //usat solo i primi 3
struct {
unsigned char ANAI0_P15_13:1; //lsb
unsigned char ANAI1_P15_14:1;
unsigned char ANAI2_P12_7:1;
unsigned char ANAI3_P12_10:1;
unsigned char ANAI4_P12_11:1;
unsigned char ANAI5_P12_12:1;
unsigned char DIN00_P15_1:1; //pulAccensione
unsigned char DIN01_P15_2:1; //fune //msb
unsigned char DIN02_P15_3:1; //funeCK
unsigned char DIN03_P15_5:1; //manovra neg
unsigned char DIN04_P15_6:1; //manovra
unsigned char DIN05_P15_8:1;
unsigned char DIN06_P15_9:1;
unsigned char DIN09_P12_2:1;
unsigned char DIN12_P12_5:1;
unsigned char DIN13_P12_9:1;
unsigned char DIN14_P9_8:1;
unsigned char OUTGS:1;
unsigned char OUTNS:1;
unsigned char enc:1;
unsigned char dummy:4;
unsigned char dummy2;
}BIT;
}IOerror_type;

if i declare and define the variable with:

IOerror_type coerenzaIngressi={0};

all work correctly.

otherwise if i write:

IOerror_type coerenzaIngressi={};

the linker consider the variable as 1byte size (wrong) and during program execution this variable overlap with another variable.

---

map file using ={};

FILE=.\src\common\coerenzaIngressi.obj
000021bd 000021bd 1
_coerenzaIngressi
000021bd 1 data ,g *
FILE=.\src\log.obj
000021be 000021d9 1c
Log::status
000021be 4 data ,g *

----

map file using ={0};

FILE=.\src\common\coerenzaIngressi.obj
000021bd 000021c0 4
_coerenzaIngressi
000021bd 4 data ,g *
FILE=.\src\log.obj
000021c1 000021dc 1c
Log::status

why does this happen? is it a bug?

  • Hi Bono,

    How's this issue so far? Were you able to find something in the CC-RX Compiler User's Manual that could explain this behavior?

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-support.renesas.com/knowledgeBase/

  • I have not found anything in the CC-RX compiler user manual that can explain this behavior.
    for the moment, when I reuse the code written previously, I check that there are no initializations of structures as {}, but it is not very reassuring to know that, if I forget one, it creates unexpected and difficult to identify bugs

  • What should be the effect of "IOerror_type coerenzaIngressi={};"?

    By default all global variables in a project are initialized after reset.

    If you write "IOerror_type coerenzaIngressi={0};" all structure elements are initialized as '0'.

    The same happens if you define "IOerror_type coerenzaIngressi;"

    It is not possible to initialize a structure with undefined values. If you want to have an uninitialized structure you have to place the variable in a new section, for example using #pragma section commands, where data is not initialized after reset.

    But I don't see a reason why you should want to do this.

  • in c ++ "IO error_type consistency Inputs = {};"
    is a zero initialization exactly like:
    "IO error_type consistency Inputs = {0};"
    for brevity, the first is often used.

    https://en.cppreference.com/w/cpp/language/zero_initialization
    but what it causes with the renesas compiler is scary: if you look at the map file, you notice that it changes the size of the structure in the compiled file and overlap another variable.

  • I tried to verify the problem, but in my code the union always took 4 byte. I could not see the problem.

    Could you provide a complete project where I could check it?

  • the original project is very complex.
    I created a small test project where the problem occurs:

    test.zip

    I report the code in full:

    options: 

    common -> cpu -> assumes the boundary alignment value for structure members is 1: active

    test.h:

    typedef union {
    unsigned long ULONG;
    unsigned char BYTE[4]; 
    }Test_type;

    test.cpp

    #include "test.h"

    #ifdef __cplusplus
    //#include <ios> // Remove the comment when you use ios
    //_SINT ios_base::Init::init_cnt; // Remove the comment when you use ios
    #endif

    void main(void);
    #ifdef __cplusplus
    extern "C" {
    void abort(void);
    }
    #endif
    Test_type var1={0};
    Test_type var2={};
    char var3=0;

    void Test() {
    var1.BYTE[1]++;
    var2.BYTE[1]++;
    var3++;
    }


    void main(void)
    {

    while (1) {
    Test();
    }

    }

    #ifdef __cplusplus
    void abort(void)
    {

    }
    #endif

     

    part of resulting MAP file:

    _var1
    00000804 4 data ,g 1 //correct
    _var2
    00000808 1 data ,g 1 //wrong!! had to be 4
    _var3
    00000809 1 data ,g 1 //ok (its char)

  • Hello,

    the problem is triggered by selecting the option "-pack" in the compiler.

    If this option is not selected the generated code looks fine.

    I also checked later compiler versions. All show the same behaviour.

  • it is obvious that removing the "-pack" option in the compiler in my example solves the problem, because on a 32bit cpu it aligns to 4 bytes avoiding the problem. but if we make a structure larger than 4 bytes the problem returns:

    test.h:

    typedef union {
    unsigned long ULONG[2];
    unsigned char BYTE[8];
    }Test_type;

    file .map:

    _var1
    00000810 8 data ,g 1
    _var2
    00000818 4 data ,g 1  //wrong: is of the same type as var1 (8 bytes)

  • I'm sorry but there seems to be a bug in the compiler when using union type variables with empty initialization list. It will be fixed in the next release of CC-RX V3.04.

    There is a work around, but it is not really feasible. For this the first element in the union has to have a size of 1 byte. So this will work:

    typedef union {
        unsigned char CHAR;

        unsigned long ULONG[2];
        unsigned char BYTE[8];
    }Test_type;

    But the better solution is to use initialization values.

  • Hi Bono,

    Just a follow up on this post. Were you able to fix this now? Did Frank's suggestions help you? Please confirm if this problem is resolved now so that we can close this thread. Thank you and have a nice day!

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-support.renesas.com/knowledgeBase/

  • Conclusion of the post: that there is a bug and it will be fixed in the next release. By using initialization {0} the problem does not occur so you can avoid the problem

  • Thanks Bono for confirming!

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-support.renesas.com/knowledgeBase/