Search code examples
cembeddedmicrochip

Why is the array at Index 1 is resetting in my compiler? (Undefined Behavior)


I do not understand why my compiler (Microchip XC16) is providing a different result to other compilers.

Below is a sample code that I converted to run on general purpose machines rather than only on the pic33fj256gp710 that I am using. When running the code on the pic (Code example 2) I get a different result where the first array index is reset to 0 (Results 2).

Essentially the idea is to get a string command in through a serial port and configure the device based upon this by breaking apart a string and sorting it.

Is this because the compiler initially passes a pointer to the value until the string is cleared rather than passing the value itself? And how can I force the compiler to pass the value itself if this is the case?

Code Example 1:

char receive_data_2[100] = "XXXX,1,4,20,33,34";

int m = 4;
char intext[10];
int output_values[10];

int number_of_logger_selections = 0;
while(receive_data_2[m] != ' ' && number_of_logger_selections < 10)
{
    int a = 0;
    m++;
    strcpy(intext, "          ");
    do
    { // get parameter number
        intext[a++] = receive_data_2[m++];
    } while(receive_data_2[m] != ',' && receive_data_2[m] != ' ');

    output_values[number_of_logger_selections] = atoi(intext); // save output number to mark 'x'

    printf
        ("\nvalue at output_values[%d] = %d, intext = %s, translated to %d\r\n\n",
         number_of_logger_selections,
         output_values[number_of_logger_selections], intext, atoi(intext));

    number_of_logger_selections++;

    int i;
    for(i = 0; i < number_of_logger_selections; i++)
    {
        printf("value at output_values[%d] = %d\r\n", i, output_values[i]);
    }
}

Results 1:

value at output_values[0] = 1, intext = 1         , translated to 1

value at output_values[0] = 1

value at output_values[1] = 4, intext = 4         , translated to 4

value at output_values[0] = 1
value at output_values[1] = 4

value at output_values[2] = 20, intext = 20        , translated to 20

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20

value at output_values[3] = 33, intext = 33        , translated to 33

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33

value at output_values[4] = 34, intext = 34, translated to 34

value at output_values[0] = 1
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33
value at output_values[4] = 34

Code Example 2:

int m = 4;
        char intext[10];
        int output_values[10];

        number_of_logger_selections = 0;
        while(receive_data_2[m] != ' ' && number_of_logger_selections < 10)
        {
            int a = 0;
            m++;
            strcpy(intext, "          ");
            do
            { // get parameter number
                intext[a++] = receive_data_2[m++];
            } while(receive_data_2[m] != ',' && receive_data_2[m] != ' ');

            output_values[number_of_logger_selections] = atoi(intext); // save output number to mark 'x'

            sprintf(transfer_data_2, "\nvalue at output_values[%d] = %d, intext = %s, translated to %d\r\n\n", number_of_logger_selections, output_values[number_of_logger_selections], intext, atoi(intext));
            SendSerialUserData(ANSI);

            number_of_logger_selections++;

            int i;
            for(i = 0; i < number_of_logger_selections; i++)
            {
                sprintf(transfer_data_2, "value at output_values[%d] = %d\r\n", i, output_values[i]);
                SendSerialUserData(ANSI);
            }
        }

Results 2:

value at output_values[0] = 1, intext = 1         , translated to 1

value at output_values[0] = 1

value at output_values[1] = 4, intext = 4         , translated to 4

value at output_values[0] = 0
value at output_values[1] = 4

value at output_values[2] = 20, intext = 20        , translated to 20

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20

value at output_values[3] = 33, intext = 33        , translated to 33

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33

value at output_values[4] = 34, intext = 34        , translated to 34

value at output_values[0] = 0
value at output_values[1] = 4
value at output_values[2] = 20
value at output_values[3] = 33
value at output_values[4] = 34

Solution

  • intext is a buffer only 10 bytes long, but you're copying 11 bytes into it (10 spaces + 1 NUL terminator). You therefore get Undefined Behaviour, and the terminator probably overwrites whatever follows the buffer in memory. What that is can indeed depend on architecture, compiler, etc., which can explain why you're seeing differences when running on different HW. But remember, Undefined Behaviour is Undefined and anything could happen.