[Answered]: Release of memory passed by reference to ESP-IDF functions

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

[Answered]: Release of memory passed by reference to ESP-IDF functions

Postby kolban » Tue Jul 18, 2017 12:42 am

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?
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

Lucas.Hutchinson
Posts: 79
Joined: Tue Apr 26, 2016 5:10 am

Re: [Question]: Release of memory passed by reference to ESP-IDF functions

Postby Lucas.Hutchinson » Tue Jul 18, 2017 3:03 am

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.

ESP_Tianhao
Posts: 28
Joined: Thu Jan 05, 2017 10:46 am

Re: [Question]: Release of memory passed by reference to ESP-IDF functions

Postby ESP_Tianhao » Thu Jul 20, 2017 3:16 am

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.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: [Question]: Release of memory passed by reference to ESP-IDF functions

Postby kolban » Thu Jul 20, 2017 3:40 am

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).
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

ESP_igrr
Posts: 1690
Joined: Tue Dec 01, 2015 8:37 am

Re: [Question]: Release of memory passed by reference to ESP-IDF functions

Postby ESP_igrr » Thu Jul 20, 2017 4:43 am

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:

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;
    }
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.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: [Question]: Release of memory passed by reference to ESP-IDF functions

Postby kolban » Thu Jul 20, 2017 4:57 am

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: braddd and 33 guests