This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

c++ array initialization on nRF9160

Hi, 

I have a C++ array or structure initialization issue that only occurs on nRF9160, but not other devices.

I am looking at the possibility of using JEDI in our IoT devices. On other devices, it runs without issues. On nRF9160, I used the mqtt_simple example as a starting point and wrote some test code to exercise JEDI features. Right at the beginning, it does not produce the expected results. I spent a few days tracking it down and eventually discovered at least one of the problem is about C++ array of structure initializations.

I have a 4-level nested structure. Each level is actually the same 48 bytes wrapped in the structure next level up. The issue is when the structure is initialized and declared as a scalar value, it is correctly initialized with the provided values. However, when it is declared as a single element array, all 48 bytes become zeros, as shown below. 

Has anyone experienced similar issues? What am I missing? What compiler flags, options, etc could lead to such a problem? Appreciate any comments and help.

The test project is attached below.

Device: nRF9160-DK

nRF Connect 3.6.1

nRF Connect SDK v1.7.1

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "bls12_381/fq.hpp"

static constexpr embedded_pairing::bls12_381::Fq scalar = {
        {{{.std_words = {0x1c7238e5, 0xcf1c38e3, 0x786f0c70, 0x1616ec6e, 0x3a6691ae, 0x21537e29, 
                         0x4d9e82ef, 0xa628f1cb, 0x2e5a7ddf, 0xa68a205b, 0x47085aba, 0xcd91de45}}}}
};

static constexpr embedded_pairing::bls12_381::Fq array[1] = {
        {{{{.std_words = {0x1c7238e5, 0xcf1c38e3, 0x786f0c70, 0x1616ec6e, 0x3a6691ae, 0x21537e29, 
                          0x4d9e82ef, 0xa628f1cb, 0x2e5a7ddf, 0xa68a205b, 0x47085aba, 0xcd91de45}}}}}
};

void print_struct(const char *title, const uint8_t *cbuf, int len)
{
    printf("\n");
    printf("[%s] %d\n", title, len);
    for (int i = 0; i < len; i++) {
        if (i % 30 == 0 && i != 0)
            printf("\n");
        else if ((i % 10 == 0 || i % 20 == 0) && i != 0)
            printf("  ");
        printf("%02X ", cbuf[i]);
    }
    printf("\n");
}

void run_tests() 
{
    print_struct("scalar", (const uint8_t *) &scalar, sizeof(scalar));
    print_struct("array", (const uint8_t *) &array[0], sizeof(array[0]));
}

[scalar] 48
E5 38 72 1C E3 38 1C CF 70 0C   6F 78 6E EC 16 16 AE 91 66 3A   29 7E 53 21 EF 82 9E 4D CB F1
28 A6 DF 7D 5A 2E 5B 20 8A A6   BA 5A 08 47 45 DE 91 CD

[array] 48
00 00 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00

array_init.zip

Parents
  • I have narrowed it down further to the following example and attached the updated project.

    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct Data {
        uint32_t words;
    };
    
    struct Overlay {
        Data val;
    };
    
    struct Inherit : Data {
    };
    
    static Overlay overlay[1] = {
            {{.words = 0xffffffff}}
    };
    
    static Inherit inherit[1] = {
            {{.words = 0xffffffff}}
    };
    
    void print_struct(const char *title, const uint8_t *cbuf, int len)
    {
        printf("[%s] %d\n", title, len);
        for (int i = 0; i < len; i++) {
            printf("%02X ", cbuf[i]);
        }
        printf("\n");
    }
    
    int main() 
    {
        print_struct("overlay", (const uint8_t *) &overlay[0], sizeof(overlay[0]));   // FF FF FF FF
        print_struct("inherit", (const uint8_t *) &inherit[0], sizeof(inherit[0]));   // 00 00 00 00  <--- Incorrect?
    
        return 0;
    }

    test_init.zip

  • Hi,

    I am not familiar enough with C++, and it's different versions, but if I change the definition of inherit to

    static Inherit inherit[1] = {
            Inherit{{.words = 0xffffffff}}
    };

    and build test_init with C++2a (the default is 11), I get

    [overlay] 4
    
    FF FF FF FF 
    
    [inherit] 4
    
    FF FF FF FF 

    You can change the C++ version to 2a by adding the following config options to your prj.conf file.

    CONFIG_CPLUSPLUS=y
    CONFIG_STD_CPP2A=y

    Best regards,

    Didrik

  • Hi, Didrik,

    Thanks for looking into it and the tip.

    Yes, changing the definition of Inherit  indeed leads to correct initialization. It also works for C++17, which I have been using. In addition, if I change the array declaration and do not specify the number of elements, i.e. from [1] to [], then it also works. So the next question is what is wrong, if any, in the original declaration? The issue appears to be a compiler bug since the same program runs correctly compiled using GCC on either a Linux PC or on other IoT devices.

    Thanks

Reply
  • Hi, Didrik,

    Thanks for looking into it and the tip.

    Yes, changing the definition of Inherit  indeed leads to correct initialization. It also works for C++17, which I have been using. In addition, if I change the array declaration and do not specify the number of elements, i.e. from [1] to [], then it also works. So the next question is what is wrong, if any, in the original declaration? The issue appears to be a compiler bug since the same program runs correctly compiled using GCC on either a Linux PC or on other IoT devices.

    Thanks

Children
Related