Утечка памяти с Libusb

Я портировал библиотеку с Linux на Windows, и во время отладки я обнаружил, что в Windows (по крайней мере, на моей машине) функция горячего подключения не поддерживается.

Итак, я решил создать обходной путь, вместо того, чтобы сильно изменять библиотеку, я взял на себя задачу эмулировать события hotplug.

Я почти завершил свою программу, но обнаружил, что у меня утечка памяти (монитор ресурсов VS2015 показывает постоянное увеличение использования оперативной памяти). Я сузился до цикла hm_monitor, но я не могу найти, где ошибка.
Средства диагностики показали, что утечка памяти происходит из Libusb-dll. образ

int delete_device(libusb_device* dev, libusb_device** list, size_t* count) {
    libusb_unref_device(dev);
    size_t i;
    int res = 0;
    for (i = 0; i < *count; i++)
        if (list[i] == dev) {
            list[i] = list[(*count) - 1];
            list[*count] = 0;
            (*count)--;
            res = 1;
            break;
        }
    return res;
}

int add_device(libusb_device* dev, libusb_device** list, size_t* count) {
    libusb_ref_device(dev);
    if (*count >= MAX_DEVICES)
        return 0;
    list[*count] = dev;
    (*count)++;
    return 1;
}

thrd_start_t hm_monitor(void* data) {
    int r; //for return values
    size_t i; //user for for loops
    ssize_t cnt; //holding number of devices in list
    hm_data_t d = (hm_data_t)data;
    libusb_device *old_devs[MAX_DEVICES] = { 0 };
    size_t old_count = 0;
    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices

    //while hm_stop is not called
    while (!d->stop) {
        //getting connected device list
        cnt = libusb_get_device_list(d->ctx, &devs);
        if (cnt < 0) {
            stop_thread(-1);//end monitor prematurely because error
        }

        //loop devs to find new devices
        for (i = 0; i < cnt; i++) {
            struct libusb_device_descriptor desc;
            int r = libusb_get_device_descriptor(devs[i], &desc);
            if (r < 0) //if device descriptor is unaccessable
                continue; //ignore it
            if (desc.idVendor == 0 || desc.idProduct == 0) //ghost device
                continue; //ignore it;
            if (!find_device(devs[i], old_devs, old_count)) { //if the device was just connected
                //add device to the old_devs
                r = add_device(devs[i], old_devs, &old_count);
                if (!r)  //if we could not add a device
                    stop_thread(-6);
                //Call on_arrived callbacks
                int c;
                for (c = 0; c < hm_state.cb_count; c++) {
                    if (hm_state.callbacks[c].fn && (hm_state.callbacks[c].dev_class == (int)desc.bDeviceClass || hm_state.callbacks[c].dev_class == -1)
                        && (hm_state.callbacks[c].vendor_id == (int)desc.idVendor || hm_state.callbacks[c].vendor_id == -1)
                        && (hm_state.callbacks[c].product_id == (int)desc.idProduct || hm_state.callbacks[c].product_id == -1))
                        if (hm_state.callbacks[c].events | LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
                            hm_state.callbacks[c].fn(d->ctx, devs[i], LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, data);
                }

            }
        }


        for (i = 0; i < old_count; i++) {
            struct libusb_device_descriptor desc;
            r = libusb_get_device_descriptor(old_devs[i], &desc);
            if (r < 0) // if somehow a device like this ended up in old_dev, delete it
            {
                delete_device(old_devs[i], old_devs, &old_count);
                continue;
            }
            if (desc.idVendor == 0 || desc.idProduct == 0)
            {
                delete_device(old_devs[i], old_devs, &old_count);
                continue;
            }
            if (!find_device(old_devs[i], devs, cnt)) {
                int c;
                for (c = 0; c < hm_state.cb_count; c++) {

                    if (hm_state.callbacks[c].fn && (hm_state.callbacks[c].dev_class == (int)desc.bDeviceClass || hm_state.callbacks[c].dev_class == -1)
                        && (hm_state.callbacks[c].vendor_id == (int)desc.idVendor || hm_state.callbacks[c].vendor_id == -1)
                        && (hm_state.callbacks[c].product_id == (int)desc.idProduct || hm_state.callbacks[c].product_id == -1))
                        if (hm_state.callbacks[c].events | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
                            hm_state.callbacks[c].fn(d->ctx, old_devs[i], LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, data);
                }
                //remove device from the list
                delete_device(old_devs[i], old_devs, &old_count);
            }
        }


        libusb_free_device_list(devs, 1); //free the list, do not unref devices becuase we unref them when they leave.

    }//END LOOP HERE

}

Список источников: страница gitlab.

Изменить: добавлен соответствующий код к вопросу.

0 ответов

Другие вопросы по тегам