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.