【问题标题】:Memory Leak scanning BLE devices内存泄漏扫描 BLE 设备
【发布时间】:2021-02-18 19:21:00
【问题描述】:

我正在使用 ESP32 扫描 BLE 广告商,但出现内存泄漏。如果我注释掉第 94 行(pBLEScan->start),泄漏就会停止,但扫描也会停止。扫描时,它按预期工作,但每次扫描泄漏大约 148 个字节。

如何识别和修复此泄漏?

我尝试了很多变化,但都无济于事。

https://pastebin.com/TsNU02h2

#include <iostream>
#include <string>
#include <Arduino.h>

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define SCAN_TIME 5

// Define a struct to hold the data on a single BLE device
struct BleDevice {
  char address[18];
  char name[80];
  char manufacturer[80];
  int appearance;
  int rssi;
  int txPower;
};

// create a static array to hold 80 BLE Devices
static struct BleDevice BleDevices[80];  
static int BleDeviceCounter = 0;

// BLE variables
BLEScan* pBLEScan;
BLEScanResults foundDevices;
static char dev_uuid[80];
static int ind = 0;           // used in loop as an index
static int lastFreeHeap = 0;
static int deviceCounter = 0;

// BLE Callback
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice adDevice) {

        if (adDevice.haveServiceUUID()) {  
            strcpy(dev_uuid, adDevice.getServiceUUID().toString().c_str());   
        } else {
            strcpy(dev_uuid, "UNKNOWN");   
        }

        if (adDevice.haveName()) {         
            strcpy(BleDevices[BleDeviceCounter].name, adDevice.getName().c_str());  
        } else {
            strcpy(BleDevices[BleDeviceCounter].name, "");
        }
        
        if (adDevice.haveManufacturerData()) {
            strcpy(BleDevices[BleDeviceCounter].manufacturer, BLEUtils::buildHexData(NULL, (uint8_t*)adDevice.getManufacturerData().data(), adDevice.getManufacturerData().length()));
        } else {
            strcpy(BleDevices[BleDeviceCounter].manufacturer, "");
        }
        
        if (adDevice.haveTXPower()) {
            BleDevices[BleDeviceCounter].txPower = adDevice.getTXPower();
        } else {
            BleDevices[BleDeviceCounter].txPower = -999;      // -999 means NULL
        }
        
        if (adDevice.haveAppearance()) {                   
            BleDevices[BleDeviceCounter].appearance = adDevice.getAppearance();
        } else {   // clear the appearance
            BleDevices[BleDeviceCounter].appearance = -999 ;  // -999 means NULL
        }
        
        strcpy(BleDevices[BleDeviceCounter].address, adDevice.getAddress().toString().c_str());
        BleDevices[BleDeviceCounter].rssi = adDevice.getRSSI();
        
        BleDeviceCounter++;    // increment the static device counter last
    }
};

void setup()
{
    Serial.begin(115200);
    Serial.println("\n\n Started...\n");

    // BLE setup
    Serial.println("Scanning for BT Devices...");
    BleDeviceCounter = 0;
    BLEDevice::init("");
    pBLEScan = BLEDevice::getScan();
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan->setActiveScan(false); 
    pBLEScan->setInterval(100);
    pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop()
{
    BleDeviceCounter = 0;   // Set counter to zero
    foundDevices = pBLEScan->start(SCAN_TIME, false);   // Start scan

    deviceCounter = BleDeviceCounter;
    for (ind=0; ind < deviceCounter; ind++) {
      Serial.printf("[%i] {address=\"%s\", rssi = \"%i\", txPower = \"%i\", mData = \"%s\", app = \"%i\", name = \"%s\"}\n", 
          ind, 
          BleDevices[ind].address, 
          BleDevices[ind].rssi, 
          BleDevices[ind].txPower, 
          BleDevices[ind].manufacturer,
          BleDevices[ind].appearance,
          BleDevices[ind].name
          );
    }

    pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
    Serial.printf("Free Heap = %i  <%i> \n", ESP.getFreeHeap(), (ESP.getFreeHeap()-lastFreeHeap));
    lastFreeHeap = ESP.getFreeHeap();
    delay(500);                // delay 1/2 second
}

//eof

【问题讨论】:

  • 通过注释掉代码我已经确定泄漏来自最长的代码行:strcpy(BleDevices[BleDeviceCounter].manufacturer, BLEUtils::buildHexData(NULL,(uint8_t*)adDevice.getManufacturerData().data(), adDevice.getManufacturerData().length()));仍然不知道为什么

标签: memory-leaks arduino bluetooth-lowenergy esp32


【解决方案1】:

事实证明,BLEUtils::buildHexData() 将分配内存并返回一个需要释放的指针。当上面的代码行替换为:

char *hex = BLEUtils::buildHexData(NULL, 
            (uint8_t*)adDevice.getManufacturerData().data(),
            adDevice.getManufacturerData().length());
strcpy(BleDevices[BleDeviceCounter].manufacturer, hex);
free(hex);

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多