char * stack variable not initialized at any optimization level
Tracking down an issue on a cortex-m4 I've distilled down to the following code
#include <stdint.h>
struct UART
{
__volatile uint32_t padding[200];
__volatile uint32_t TXD;
};
#define NRF_UARTE0 ((__volatile__ struct UART*)0x40002000)
int main(void)
{
char str[] = "hello\n";
NRF_UARTE0->TXD = (uint32_t)(str);
}
The original code was somewhat longer but TXD is a pointer to a buffer to be sent out of a UART, the full code, after setting TXD, starts the UART and waits for completion.
Compiled with -Os (or -O1, O2, O3) like this
gcc-arm-
yields the following assembler
00000000 <main>:
0: 4b02 ldr r3, [pc, #8] ; (c <main+0xc>)
2: b082 sub sp, #8
4: f8c3 d320 str.w sp, [r3, #800] ; 0x320
8: b002 add sp, #8
a: 4770 bx lr
c: 40002000 .word 0x40002000
8 bytes have been allocated on the stack for 'str' and then the sp is written to r3+0x320 which is the TXD field. However the stack is never initialized with the 'hello' string. In the full code the UART is then started and sends random garbage from the uninitialized memory.
The .o file doesn't even contain the string 'hello', it's been completely removed.
It's rather gross to initialize an on-stack string like that, but as far as I can tell it's valid C, the memory is allocated on stack, the address is written to TXD, the compiler has no way of knowing what that write does and so should initialize the memory correctly as the code specifies before using it.
if you make str volatile, it initializes properly, which makes no more sense. There are of course other workarounds like using a char* but I think this code as-written should work.
Bug I should file, or my imperfect understanding of C?
Question information
- Language:
- English Edit question
- Status:
- Solved
- Assignee:
- No assignee Edit question
- Solved by:
- Tejas Belagod
- Solved:
- Last query:
- Last reply: