Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

No deep copy of ble_advertising_init_t for ble_advertising_init()

I have now spent a significant amount of hours debugging strange problems with my advertising. It turned out that it is very important how you set up the init structure for ble_advertising_init() as the structure is not deep copied inside the ble_advertising_init() function. To me this is quite a serious problem as it is really hard to trace when these problems arise.

In the documentation for ble_advertising_init() it is stated that "The supplied advertising data is copied to a local structure" which led me into believing that all the data was just copied. But it turns out that it is no deep copy, as in some cases only pointers are copied.

One example is the advdata.uuids_complete.p_uuids. Here, only the pointer is copied. In my code I set up these as auto variables which was wrong:

ble_uuid_t m_adv_uuids[] = {{0x1234, BLE_UUID_TYPE_BLE}};

advdata.uuids_complete.p_uuids  = m_adv_uuids;

 

But looking inside the ble_advertising_init() function, only the pointer to this is copied:

p_advertising->advdata.uuids_complete = p_init->advdata.uuids_complete;

This leaves my uuids dangling on the stack which is a very dangerous situation.

I would have needed more information about this in the documentation: Which parts of the init structure am I responsible for keeping in memory.

Edit:

I have now searched my code and found that also the advdata.p_tx_power_level is the responsibility of the user, it is not deep copied. The advdata.p_manuf_specific_data for example seems to be deep copied which is good.

  • Hi,

    which led me into believing that all the data was just copied. But it turns out that it is no deep copy, as in some cases only pointers are copied.

    I can see the confusion, and it should maybe have been better described that not all parts of the structure are copied.

    What is the purpose of using auto variables? Normaly this is not a problem with variables declared like you show above (ble_uuid_t m_adv_uuids).

    Best regards.
    Jørgen

  • The problem is that the declaration ble_uuid_t m_adv_uuids means that my variables are put on the stack. The pointer to these variables are then copied inside ble_advertising_init() and appears in m_advertising. My code then leaves the function advertising_init() which renders the stack variables invalid. m_advertising is then used in other places, for example in ble_advertising_start(). ble_advertising_start() will then use these variables from the stack, which at that time probably are overwritten by something else.

    Edit: In this case it is forbidden to use "ble_uuid_t m_adv_uuids", as the pointer will later be used out of context. It must be either "static ble_uuid_t m_adv_uuids", or declared globally outside the function.

  • Sorry, I missed this in my previous answer. You will of course also need static for this to work. Unfortunately, it is not well documented in alle the SDK libraries documentation which functions require static variables and which does not. You will have to check the source code if this is not stated, and RAM consumption is an issue for you.

Related