Page 1 of 1

Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 2:02 am
by NatKarmios
I currently have a simple program that sets up a framebuffer that can be written to.

I am encountering behaviour where values stored i arrays, once retrieved, come back as seemingly random values, with no relation to the originals.
I have also noticed some similarly strange and.unexpected behaviour from switch statements - I suspect this has something to do with how both arrays and switch statements are statically allocated in memory.

As an example, here I have some code that should draw a hardcoded number, followed by 7 other hardcoded numbers that have been stored in an array:

Code: Select all

int cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
drawNum(&display, 0x1234ABCD);
for (int i=0; i<7; i++)
  drawNum(&display, cols[i]);
And this is the result (note that text is drawn from the bottom upwards):
Image

As you can quite clearly see, all the array-stored values come back as wildly different to what is expected.

Is this a known problem? Anyone know of a workaround or a solution?

Many thanks for your time.

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 4:37 am
by lpoulain
One thing I notice is that you are using an int type (so signed integers), but have numbers in your array which are negative numbers. You might want to use unsigned integers instead.

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 9:48 am
by NatKarmios
lpoulain wrote:
Sun Jun 16, 2019 4:37 am
One thing I notice is that you are using an int type (so signed integers), but have numbers in your array which are negative numbers. You might want to use unsigned integers instead.
Good spot, though unfortunately this has no effect. I expect this is because drawNum() uses bitwise logic.

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 9:55 am
by NatKarmios
An interesting development; if I assign the array values at runtime like so:

Code: Select all

unsigned int cols[7];
cols[0] = 0xFFFF0000;
cols[1] = 0xFFFF7F00;
cols[2] = 0xFFFFFF00;
cols[3] = 0xFF00FF00;
cols[4] = 0xFF0000FF;
cols[5] = 0xFF4B0082;
cols[6] = 0xFF9400D3;
drawNum(&display, 0x1234ABCD);
drawNum(&display, (int)cols);
for (int i=0; i<7; i++)
  drawNum(&display, cols[i]);
...then the numbers are rendered fine. Potentially something at compile-time messing this up?

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 3:27 pm
by LdB
Most likely your linker file isn't saving the rodata section which is the one the constant data will go into, so basically your file doesn't actually contain the constant array and is printing junk.

Without changing the linker file try putting the array in the text section ... something like

Code: Select all

int  __attribute__((section("text"))) cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 5:48 pm
by Nabushika
LdB wrote:
Sun Jun 16, 2019 3:27 pm
Most likely your linker file isn't saving the rodata section which is the one the constant data will go into, so basically your file doesn't actually contain the constant array and is printing junk.

Without changing the linker file try putting the array in the text section ... something like

Code: Select all

int  __attribute__((section("text"))) cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
This didn't work, data was still garbled. Any other suggestions? Or anything we can do to fix the linking?

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 7:13 pm
by NatKarmios
LdB wrote:
Sun Jun 16, 2019 3:27 pm
Most likely your linker file isn't saving the rodata section which is the one the constant data will go into, so basically your file doesn't actually contain the constant array and is printing junk.

Without changing the linker file try putting the array in the text section ... something like

Code: Select all

int  __attribute__((section("text"))) cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
This has no effect :(
Seemingly random numbers are still displayed.

Re: Unexpected behaviour of arrays and switch statements

Posted: Sun Jun 16, 2019 11:59 pm
by lpoulain
What happens if you try the following scenarios:

Code: Select all

drawNum(&display, 0xFFFF0000);

Code: Select all

int cols[0] = { 0x1234ABCD };
drawNum(&display, cols[0]);
Other things you can try:
  • If you are using UART, print the array numbers there at various point of your program to see if they are defined properly at one point
  • Perform a memory dump of your array to make sure it contains the right data.
  • Disassemble your code (objdump -d -S yourfile.o)

Re: Unexpected behaviour of arrays and switch statements

Posted: Mon Jun 17, 2019 6:45 am
by LdB
I suspect we need to see your linker file and the function drawNum because it is obviously having issues with constant arrays.

Re: Unexpected behaviour of arrays and switch statements

Posted: Mon Jun 17, 2019 9:52 am
by NatKarmios
LdB wrote:
Mon Jun 17, 2019 6:45 am
I suspect we need to see your linker file and the function drawNum because it is obviously having issues with constant arrays.
The linker file:
https://gist.github.com/NatKarmios/9a15 ... 4770797dae

I highly doubt drawNum() is having an effect, but here it is just in case:

Code: Select all

void drawNum(display_t *display, unsigned int num) {
  int y = display->height - (display->debugLinesPrinted*7);

  for (int i=0; i<8; i++) {
    int numData = getNumData((num >> (28-(4*i))) & 0xF);
    drawChar(display, i*6, y, numData);
  }

  newLine(display, 8);
}

Re: Unexpected behaviour of arrays and switch statements

Posted: Mon Jun 17, 2019 12:30 pm
by LdB
That should work, I cant see any problem.

I guess it has to be a weird compiler bug have you checked for updates?

You could try the other three ways to write the array

Code: Select all

static const int  cols[7] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
static int  cols[] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };
static const int  cols[] = { 0xFFFF0000, 0xFFFF7F00, 0xFFFFFF00, 0xFF00FF00, 0xFF0000FF, 0xFF4B0082, 0xFF9400D3 };