0

Using MCUXpresso with NXP MKL02Z16VFM4 for reference.

When I declare a struct like so

typedef struct {
        uint8_t DATA :8;
} myStruct;
myStruct xxx __attribute__ ((section ("xyz")));

the position in memory is filled with random characters. The processor is little endian so when I try to access this address, I get those random characters and the data I have written to the struct.

//At address 0x1FFFFE84 : BD84D1E4

xxx.DATA = 0xAA; //Assign some numbers to struct

//Now, 0x1FFFFE84 : BD84D1AA

I can use memset to clear the memory, but I'd like to know why the memory is filled with these random characters when declaring a struct.

555
  • 1
  • 1
    Nothing in the C standard requires initializing memory, the programmer is responsible for that. – yano Nov 18 '19 at 16:37
  • what is the significance of address `0x1FFFFE84`? That must not be the address of `xxx.DATA`. – yano Nov 18 '19 at 16:43
  • It would be easier to answer your question if you stated what you expected and why. It's not clear what you need explained to you -- you've cited a case of something doing exactly what someone would expect and it's not clear what you want an explanation for. – David Schwartz Nov 18 '19 at 16:59
  • 2
    @yano : Data with static storage class without an initialiser _are_ required to be zero initialised. Given the `__attribute__` it seems like this is a global declaration therefore static. Perhaps that is the source of the "surprise"? The section allocation will defeat the zero initialisation. – Clifford Nov 18 '19 at 17:03
  • @Clifford ah yes, that makes sense, could be. – yano Nov 18 '19 at 17:07
  • Relying on .bss/.data initialization in your C code is bad practice in embedded systems, because it is a very common non-standard extension to skip such overhead code during start-up. And custom sections aren't even .bss/.data. – Lundin Nov 19 '19 at 07:30
  • I should mention that I have created section 'xyz' in .data in the linker script, 0X1FFFFE84 is the start address of this section. Fair points made @all. – 555 Nov 19 '19 at 09:19
  • You still need ot be certain whet your start-up code is doing. I understand that MCUXpresso uses GCC, in which case you should have a source file crt0.s (which may in turn call other code in C or assembler) - that is where system and runtime environment are initialised before `main()` is invoked - it uses information generated by the linker directed by the linker .ld script. You can see for yourself why the section is not initialised. – Clifford Nov 19 '19 at 14:12
  • Do you you get the same result is you _don't_ use the section attribute and let the linker do its job? If so, don't confuse the question with that extraneous information. Rather than hiding in a comment, you might mention your linker configuration and include your .ld script in the question. Possibly even tour crt0.s and related start-up files. – Clifford Nov 19 '19 at 14:13

2 Answers2

3

You have explicitly located xxx in section xyz - this section is unknown to the compiler and the default start-up code, so need not be explicitly zero initialised as the default bss segment would be. For most volatile memory technologies, memory has non-deterministic content at power up - hence apparently random in this case.

If you expect zero initialisation of private sections, you need to explicitly add that in your linker script and/or start-up code. The content of the unused memory surrounding the struct or any alignment padding within it however is irrelevant and explicitly clearing it to some known value is largely unnecessary.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

A struct variable, but actually ANY variable, needs to be initialized before being used in the code. Accessing (reading) uninitialized data causes undefined behavior, meaning that there's not guarancy that the compiler will behave in a predictable way.

Most compilers set to 0uninitialized variables, but some other compilers (some embedded compilers, for example) don't. And that's why you see random values.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
  • I've tried initializing with zeros ```myStruct xxx __attribute__ ((section ("xyz"))) = {0};``` but this does not seem to have any effect. I think I understand the reasoning behind the random values though, thanks. – 555 Nov 18 '19 at 16:39
  • The random values are noise or previous use of the RAM. You might want to loop through the bytes you have allocated and set each of them to zero. I'm not familiar with the system being used here but in the c library I typically use memset(&xxx, 0, sizeof(myStruct)) – NTDLS Nov 18 '19 at 17:04
  • It sounds strange: `myStruct xxx = {0};` as far as I know should initialize your struct to 0 even without section attribute (but I have to say I don't know your uC). Is it a global variable? – Roberto Caboni Nov 18 '19 at 17:07
  • 1
    @555 : The run-time startup initialises the BSS and DATA segments by default - your object is in `xyz` so either zero or explicit initialisation will be ignored unless you modify the start-up code to deal with your custom section. – Clifford Nov 18 '19 at 17:18
  • @Cubo78 : fair assumption that it is global - placing a non-static local in a section makes no sense. – Clifford Nov 18 '19 at 17:19
  • 1
    Only the BSS section will normally be zero initialised - this data is not located in the BSS. It has nothing to do with "embedded compilers" omitting zero initialisation (which is not generally true in any case - only sometimes). – Clifford Nov 18 '19 at 17:25
  • @Clifford 'global variable question' was just to detect any mistake (would have it been reported by the compiler? I have no idea). Talking about embedded compilers, it was an example in which I just need to be more clear. My edit should improve the answer. ;) – Roberto Caboni Nov 18 '19 at 17:32
  • Essentially your whole answer is incorrect, you don't even mention storage duration. "ANY variable, needs to be initialized before being used" is strictly speaking not true, variables with static storage duration are implicitly zero-initialized in a standard compliant environment. "Accessing (reading) uninitialized data causes undefined behavior" is not true either, there's a lot of special cases. It is generally _unspecified_ behavior, not undefined. See [this](https://stackoverflow.com/a/40674888/584518). – Lundin Nov 19 '19 at 07:35
  • @Lundin also *non standard compliant environments* exist, especially in very basic embedded environments. I've worked with them and I know what I'm writing about. So I definitely confirm my statement. Even against downvoters. – Roberto Caboni Nov 19 '19 at 07:48
  • @Cubo78 It doesn't make sense without context, nor without mentioning storage duration. For example no compiler, standard compliant or not, initializes automatic or allocated storage duration variables. – Lundin Nov 19 '19 at 07:50
  • The *question* is the context. And in this context we had potential undefined behavior due to uninitialized variable. – Roberto Caboni Nov 19 '19 at 08:03