There are some functions that take a pointer to memory as inputs. What, if anything, can we say about the ability to release this memory after an API call?
For example, imagine the following pseudo code:
uint8_t *pMem = malloc(size);
some_esp_idf_function(pMem);
free(pMem);
Do we have confidence that when an ESP-IDF function returns, it won't still have kept a reference to some of the memory?
Here is a concrete example that caused me to think along these lines. There is a function called:
esp_ble_gatts_add_char() - see http://esp-idf.readthedocs.io/en/latest ... _control_t
one of its parameters is "char_val" which is a pointer to storage. When esp_ble_gatts_add_char() returns, may I release the storage I allocated to pass into the call?
[Answered]: Release of memory passed by reference to ESP-IDF functions
[Answered]: Release of memory passed by reference to ESP-IDF functions
Last edited by kolban on Thu Jul 20, 2017 4:57 am, edited 1 time in total.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
-
- Posts: 79
- Joined: Tue Apr 26, 2016 5:10 am
Re: [Question]: Release of memory passed by reference to ESP-IDF functions
I would also be interested in this.
It would save a decent amount of statically allocated ram in my current application if this ram could be malloc'd then free'd.
Currently I have err'ed on the side of caution and statically allocated the required memory for each characteristic.
It would save a decent amount of statically allocated ram in my current application if this ram could be malloc'd then free'd.
Currently I have err'ed on the side of caution and statically allocated the required memory for each characteristic.
-
- Posts: 28
- Joined: Thu Jan 05, 2017 10:46 am
Re: [Question]: Release of memory passed by reference to ESP-IDF functions
Thank you, Kolban.
Actually, we usually follow this rule: who allocate memory, who free memory.
For `esp_ble_gatts_add_char()`, is the same, char_uuid (point) need to free by application, if application malloc it.
If there's some special usage, we will specify it in comment. If we don't , it's our mistake.
Actually, we usually follow this rule: who allocate memory, who free memory.
For `esp_ble_gatts_add_char()`, is the same, char_uuid (point) need to free by application, if application malloc it.
If there's some special usage, we will specify it in comment. If we don't , it's our mistake.
Re: [Question]: Release of memory passed by reference to ESP-IDF functions
Thank you sir. I wasn't clear in my original question.
My question isn't "WHO" should release the memory ... I fully believe in the "you allocated it, you free it" policy ... my question is "WHEN" is it safe to release it?
For example ... is the following safe:
uint8_t* pdata = malloc(20);
// populate data
esp_ble_send(pData, 20);
free(pData); // This free IMMEDIATELY follows the send
Can I immediately free data after having passed a reference to the data to an ESP-IDF function? My fear is that some ESP functions execute asynchronously and may require that a passed in memory pointer be "maintained" until some time in the future (for example, keep the memory around until a send response event is received).
My question isn't "WHO" should release the memory ... I fully believe in the "you allocated it, you free it" policy ... my question is "WHEN" is it safe to release it?
For example ... is the following safe:
uint8_t* pdata = malloc(20);
// populate data
esp_ble_send(pData, 20);
free(pData); // This free IMMEDIATELY follows the send
Can I immediately free data after having passed a reference to the data to an ESP-IDF function? My fear is that some ESP functions execute asynchronously and may require that a passed in memory pointer be "maintained" until some time in the future (for example, keep the memory around until a send response event is received).
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: [Question]: Release of memory passed by reference to ESP-IDF functions
This should probably be mentioned in function documentation, but in the meantime we can start by looking at the code...
We see that the pointer to the buffer you pass to BLE functions (such as esp_ble_gatts_add_char) is stored into a btc_ble_gatts_args_t structure, allocated on the stack. The code passes a pointer to this structure to btc_transfer_context, along with a pointer to btc_gatts_arg_deep_copy function. Deep copy, looks like we are on the right track.
Looking at the source code of that function, we see a large switch for all the argument types. For example for add_char, the code looks like this:
So you see that the pointer to attr_value (which came from your application!) is replaced with a pointer to a new buffer, allocated using GKI_getbuf, which is initialized with the same contents. This is deep copying: not only the structure itself is copied, but all the data it references also gets copied.
Summarizing this, it is safe to free application buffer immediately. I suppose this is what we need to say in the docs somewhere: functions do not assume ownership of data, unless mentioned otherwise.
We see that the pointer to the buffer you pass to BLE functions (such as esp_ble_gatts_add_char) is stored into a btc_ble_gatts_args_t structure, allocated on the stack. The code passes a pointer to this structure to btc_transfer_context, along with a pointer to btc_gatts_arg_deep_copy function. Deep copy, looks like we are on the right track.
Looking at the source code of that function, we see a large switch for all the argument types. For example for add_char, the code looks like this:
Code: Select all
case BTC_GATTS_ACT_ADD_CHAR:{
if (src->add_char.char_val.attr_value != NULL){
dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len);
if(dst->add_char.char_val.attr_value != NULL){
memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value,
src->add_char.char_val.attr_len);
}else{
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
}
}
break;
}
Summarizing this, it is safe to free application buffer immediately. I suppose this is what we need to say in the docs somewhere: functions do not assume ownership of data, unless mentioned otherwise.
Re: [Question]: Release of memory passed by reference to ESP-IDF functions
Perfect ... thank you sir. I'll assume that deep copies are the norm/expected unless explicitly stated in any of the documentation. If we find places where that is not the case (memory must remain involute but isn't documented as such), we'll raise an issue.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Who is online
Users browsing this forum: chudofthecosmos and 84 guests