将 shared_ptr 与 FreeRTOS 队列一起使用

val*_*ica 5 c++ smart-pointers freertos

我使用 ESP-32 并且需要std::shared_ptr使用 FreeRTOS 队列通过。然而,它失去了一个链接。我认为这是问题的根源:

#include <iostream>
#include <memory>
#define PRINT_USE_COUNT(p) std::cout << "Use count: " << p.use_count() << std::endl;

extern "C" {
    #include <freertos/FreeRTOS.h>
    #include <freertos/task.h>
    #include <freertos/queue.h>
}

class testClass {
    public:
        testClass() {
            std::cout << "Class is constructed" << std::endl;
        };
        virtual ~testClass() {
            std::cout << "Class is destructed" << std::endl;
        };
};

struct container {
    std::shared_ptr<testClass> field;
};

extern "C" void app_main(void) {
    auto queue = xQueueCreate(1, sizeof(container));
    auto p = std::make_shared<testClass>();
    PRINT_USE_COUNT(p); // 1
    {
        container c;
        c.field = p;
        PRINT_USE_COUNT(p); // 2
        xQueueSendToBack(queue, &c, 0);
        PRINT_USE_COUNT(p); // 2
    }
    PRINT_USE_COUNT(p); // 1 (Ooops!)
    {
        container c;
        assert(xQueueReceive(queue, &c, 0) == pdTRUE);
        PRINT_USE_COUNT(c.field); // 1
    }
    // Class is destructed
    std::cout << "Test finished" << std::endl;
    vQueueDelete(queue);
}
Run Code Online (Sandbox Code Playgroud)

所以队列中有一个指针,但它没有被计算在内!

我该如何解决这个问题(并尽可能继续使用 FreeRTOS 队列)?使用std::move没有帮助。

Clo*_*onk 3

C 风格的原始指针队列仅适用于 C++shared_ptr,当且仅当std::is_trivial<T>::value为 true(主要是 POD 或普通可复制对象)。

由于存在 memcpy 和其他操作内存的普通 C 操作,因此引用计数将无法正确处理(因为它是幕后的 C 代码,并且不会调用析构函数等),并且最终可能会导致内存泄漏。

没有简单的方法可以避免这个问题,但最好的方法是自己管理内存。

另请参阅这个问题:FreeRTOS 中的共享指针和队列