espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.52k stars 7.39k forks source link

BLE library has a memory leak. #4753

Closed ushiboy closed 3 years ago

ushiboy commented 3 years ago

Hardware:

Board: ESP32 Dev Module Core Installation version: 1.0.5-rc6 IDE name: Arduino IDE 1.8.13 Flash Frequency: 80Mhz PSRAM enabled: no Upload Speed: 921600 Computer OS: Ubuntu 18.04.5 LTS

Description:

I ran the following code as a central device for BLE. Then the free space in the heap memory gradually decreased and finally the device hung. I used the BLE_server sample sketch for the peripherals.

Sketch:

#include "src/BLEDevice.h"

static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");

uint32_t count = 0;
static boolean doConnect = false;
static boolean doScan = false;
static BLEAdvertisedDevice *myDevice;

bool connectToServer()
{
  BLEClient *pClient = BLEDevice::createClient();
  if (!pClient->connect(myDevice))
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    return false;
  }

  BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr)
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  if (pRemoteCharacteristic == nullptr)
  {
    Serial.print("Failed to find our characteristic UUID: ");
    Serial.println(charUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  if (pRemoteCharacteristic->canRead())
  {
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());
  }

  pClient->disconnect();
  return true;
}

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
  void onResult(BLEAdvertisedDevice advertisedDevice)
  {
    doScan = true;
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID))
    {
      BLEDevice::getScan()->stop();
      if (myDevice != nullptr)
      {
        delete myDevice;
      }
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = false;
    }
  }
};

void setup()
{
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
  BLEScan *pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);
}

void loop()
{
  if (doConnect)
  {
    count++;
    Serial.printf("Count: %d\n", count);
    Serial.printf("Free Heap Size: %d\n", esp_get_free_heap_size());
    Serial.printf("System Free Heap Size: %d\n", system_get_free_heap_size());
    Serial.printf("Minimum Free Heap Size: %d\n", esp_get_minimum_free_heap_size());

    connectToServer();
    doConnect = false;
    doScan = true;
  }
  else if (doScan)
  {
    doScan = false;
    BLEDevice::getScan()->start(0);
  }

  delay(1000);
}

Debug Messages:

Count: 47
Free Heap Size: 6896
System Free Heap Size: 6896
Minimum Free Heap Size: 1812
[V][BLEDevice.cpp:60] createClient(): >> createClient
[V][BLEDevice.cpp:66] createClient(): << createClient
[V][BLEClient.cpp:96] connect(): >> connect(80:7d:3a:dc:d5:4a)
[I][BLEDevice.cpp:614] addPeerDevice(): add conn_id: 46, GATT role: client
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: RegEvt (0x3fffee78), owner: <N/A> for connect
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: RegEvt (0x3fffee78), owner: connect
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: RegEvt (0x3fffee78), owner: connect for connect
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: RegEvt (0x3fffee78), owner: connect
[V][FreeRTOS.cpp:77] wait(): << wait: Semaphore released: name: RegEvt (0x3fffee78), owner: <N/A>
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: OpenEvt (0x3fffff4c), owner: <N/A> for connect
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: OpenEvt (0x3fffff4c), owner: connect
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: OpenEvt (0x3fffff4c), owner: connect for connect
h2zero commented 3 years ago

Your memory leak is because you create a new BLEClient instance every time connectToServer() is called and returning without deleting the instance. Also, if you want to save a lot of memory try using NimBLE.

chegewara commented 3 years ago

BLEClient should be deleted by library after disconnecting, but i agree, try to use NimBLE, more pros than cons.

ushiboy commented 3 years ago

Thanks for the reply.

I fixed it to delete the client at the end of connectToServer, but now the device crashes.

bool connectToServer()
{
  BLEClient *pClient = BLEDevice::createClient();
  if (!pClient->connect(myDevice))
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    return false;
  }

  BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr)
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  if (pRemoteCharacteristic == nullptr)
  {
    Serial.print("Failed to find our characteristic UUID: ");
    Serial.println(charUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  if (pRemoteCharacteristic->canRead())
  {
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());
  }

  pClient->disconnect();
  delete pClient;   // added
  return true;
}

Here is the log.

Count: 3
Free Heap Size: 138840
System Free Heap Size: 138840
Minimum Free Heap Size: 130840
[V][BLEDevice.cpp:60] createClient(): >> createClient
[V][BLEDevice.cpp:66] createClient(): << createClient
[V][BLEClient.cpp:96] connect(): >> connect(80:7d:3a:dc:d5:4a)
[I][BLEDevice.cpp:614] addPeerDevice(): add conn_id: 2, GATT role: client
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: RegEvt (0x3ffdf304), owner: <N/A> for connect
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: RegEvt (0x3ffdf304), owner: connect
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: RegEvt (0x3ffdf304), owner: connect for connect
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: RegEvt (0x3ffdf304), owner: connect
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 0
[V][FreeRTOS.cpp:77] wait(): << wait: Semaphore released: name: RegEvt (0x3ffdf304), owner: <N/A>
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: OpenEvt (0x3ffdd44c), owner: <N/A> for connect
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: RegEvt (0x3ffdf304), owner: <N/A>
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: OpenEvt (0x3ffdd44c), owner: connect
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: OpenEvt (0x3ffdd44c), owner: connect for connect
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 5] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 40
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 2
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 2
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 2
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: OpenEvt (0x3ffdd44c), owner: connect
[V][FreeRTOS.cpp:77] wait(): << wait: Semaphore released: name: OpenEvt (0x3ffdd44c), owner: <N/A>
[V][BLEClient.cpp:131] connect(): << connect(), rc=1
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 2
[V][BLEClient.cpp:386] getService(): >> getService: uuid: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEClient.cpp:422] getServices(): >> getServices
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: OpenEvt (0x3ffdd44c), owner: <N/A>
[V][BLEClient.cpp:71] clearServices(): >> clearServices
[V][BLEClient.cpp:78] clearServices(): << clearServices
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: SearchCmplEvt (0x3ffdd4ac), owner: <N/A> for getServices
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: SearchCmplEvt (0x3ffdd4ac), owner: getServices
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: SearchCmplEvt (0x3ffdd4ac), owner: getServices for getServices
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 7
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteService.cpp:26] BLERemoteService(): >> BLERemoteService()
[V][BLERemoteService.cpp:34] BLERemoteService(): << BLERemoteService()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 6
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 6
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 6
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: SearchCmplEvt (0x3ffdd4ac), owner: getServices
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 6
[V][FreeRTOS.cpp:77] wait(): << wait: Semaphore released: name: SearchCmplEvt (0x3ffdd4ac), owner: <N/A>
[V][BLEClient.cpp:439] getServices(): << getServices
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEClient.cpp:399] getService(): << getService: found the service with uuid: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: SearchCmplEvt (0x3ffdd4ac), owner: <N/A>
[V][BLERemoteService.cpp:162] retrieveCharacteristics(): >> getCharacteristics() for service: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[D][BLERemoteService.cpp:193] retrieveCharacteristics(): Found a characteristic: Handle: 42, UUID: beb5483e-36e1-4688-b7f5-ea07361b26a8
[V][BLERemoteCharacteristic.cpp:36] BLERemoteCharacteristic(): >> BLERemoteCharacteristic: handle: 42 0x42, uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8
[V][BLERemoteCharacteristic.cpp:258] retrieveDescriptors(): >> retrieveDescriptors() for characteristic: beb5483e-36e1-4688-b7f5-ea07361b26a8
[E][BLERemoteCharacteristic.cpp:282] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
[V][BLERemoteCharacteristic.cpp:302] retrieveDescriptors(): << retrieveDescriptors(): Found 0 descriptors.
[V][BLERemoteCharacteristic.cpp:46] BLERemoteCharacteristic(): << BLERemoteCharacteristic
[V][BLERemoteService.cpp:209] retrieveCharacteristics(): << getCharacteristics()
[V][BLERemoteCharacteristic.cpp:417] readValue(): >> readValue(): uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8, handle: 42 0x2a
[V][FreeRTOS.cpp:189] take(): Semaphore taking: name: ReadCharEvt (0x3ffdf71c), owner: <N/A> for readValue
[V][FreeRTOS.cpp:198] take(): Semaphore taken:  name: ReadCharEvt (0x3ffdf71c), owner: readValue
[V][FreeRTOS.cpp:63] wait(): >> wait: Semaphore waiting: name: ReadCharEvt (0x3ffdf71c), owner: readValue for readValue
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 3
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 3
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 3
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: ReadCharEvt (0x3ffdf71c), owner: readValue
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 3
[V][FreeRTOS.cpp:77] wait(): << wait: Semaphore released: name: ReadCharEvt (0x3ffdf71c), owner: <N/A>
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLERemoteCharacteristic.cpp:445] readValue(): << readValue(): length: 21
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: ReadCharEvt (0x3ffdf71c), owner: <N/A>
[V][BLEClient.cpp:141] disconnect(): >> disconnect()
[V][BLEClient.cpp:147] disconnect(): << disconnect()
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 5
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 5
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 5
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 5
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 5] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[V][BLEUtils.cpp:1283] dumpGattClientEvent(): GATT Event: Unknown
[V][BLEUtils.cpp:951] gattClientEventTypeToString(): Unknown GATT Client event type: 41
[D][BLEClient.cpp:160] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 6] ... Unknown
[V][FreeRTOS.cpp:143] give(): Semaphore giving: name: OpenEvt (0x3ffdd44c), owner: <N/A>
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:720 (xQueueGenericSend)- assert failed!
abort() was called at PC 0x4008d9bc on core 0

Backtrace: 0x40091498:0x3ffcdf90 0x400916c9:0x3ffcdfb0 0x4008d9bc:0x3ffcdfd0 0x400d8a5d:0x3ffce010 0x400d8a91:0x3ffce050 0x400d4529:0x3ffce070 0x400d54b9:0x3ffce120 0x40106aae:0x3ffce190 0x400ff83a:0x3ffce1e0 0x4008e089:0x3ffce210

Rebooting...

I'll refer to NimBLE.

h2zero commented 3 years ago

BLEClient should be deleted by library after disconnecting

Oops, I forgot about this, sorry for bad info. Curious about the memory leak then.

ushiboy commented 3 years ago

I've tried different approach.

Changed the client to a global variable and delete the previous instance before create a new instance. (It's not good enough, it still crashes occasionally)

static BLEClient *pClient;

bool connectToServer()
{
  if (pClient != nullptr)
  {
    delete pClient;
  }
  pClient = BLEDevice::createClient();
  if (!pClient->connect(myDevice))
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    return false;
  }

  BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr)
  {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  if (pRemoteCharacteristic == nullptr)
  {
    Serial.print("Failed to find our characteristic UUID: ");
    Serial.println(charUUID.toString().c_str());
    pClient->disconnect();
    return false;
  }

  if (pRemoteCharacteristic->canRead())
  {
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());
  }

  pClient->disconnect();
  return true;
}

I used the serial plotter in the Arduino IDE to plot the heap size, and it looks like this heap-size

For Your Information

h2zero commented 3 years ago

Good approach, definitely looks like there's some bugs to stomp.

ushiboy commented 3 years ago

The crashes that sometimes occurred with the above approach seem to have gone away after the following modification to the BLEClient destructor.

BLEClient::~BLEClient() {
    // We may have allocated service references associated with this client.  Before we are finished
    // with the client, we must release resources.
    for (auto &myPair : m_servicesMap) {
       delete myPair.second;
    }
    m_servicesMap.clear();
    m_servicesMapByInstID.clear();  // added
} // ~BLEClient

But, the free space in the heap memory is still decreasing.

ushiboy commented 3 years ago

I found the cause. The m_rawData variable was not released in the destructor of BLERemoteCharacteristic. I made the following changes to the destructor.

BLERemoteCharacteristic::~BLERemoteCharacteristic() {
    removeDescriptors();   // Release resources for any descriptor information we may have allocated.
    if (m_rawData != nullptr)
    {
        free(m_rawData);
    }
} // ~BLERemoteCharacteristic

The graph of free heap memory space after the change is as follows. fixed

everslick commented 3 years ago

just a side note: it is perfectly legal to call free() or delete() on a nullptr, so any check that only guards one of the two calls is unnecessary at best or confusing otherwise.

ushiboy commented 3 years ago

Thanks for your advice. I will remove the guards.