gpt4 book ai didi

c++ - 为什么这个指向结构的指针的 std::queue/list 直到 List.Size() == 0 才释放内存?

转载 作者:行者123 更新时间:2023-12-01 13:08:19 26 4
gpt4 key购买 nike

我有一个程序将指向包含 cv::mat 克隆的结构的指针提供给其他线程使用的 std::queue/std::list (两者都尝试过)。
读取/创建速度很快,但消耗速度很慢,因此队列会随着时间的推移而增长。
这个队列变得很大,很容易占用超过 50% 的系统内存。
当读取/创建停止时,队列会缩小,但内存不会!
当队列大小最终达到 0 时,内存几乎立即消失。 queue.size() == 0 触发器可以通过确保队列永远不会弹出最后一个指针来确认——内存不会消失。
*注意:队列仍然存在,它没有超出范围,是静态的。
所以我有两个问题:

  • 为什么队列大小为零时内存会消失?或者换句话说,为什么当指针被消耗/删除时内存不会消失?
  • 如何显式释放内存?

  • 代码是这样的:
    struct MyStruct {
    cv::mat matA;
    ~MyStruct(){
    cout << "Yeah, destructor is called!" << endl;
    //matA.release(); //Not needed, right? Adding it does not change anything.
    }
    };

    static queue<shared_ptr<MyStruct>> awaitingProcessing;
    static mutex queueGuard;
    线程 1(队列填充):
    BYTE* buffer = (BYTE*)malloc(dataWidth*dataHeight);
    while(signal){
    LoadData(buffer);
    cv::Mat data = cv::Mat(dataHeight, dataWidth, CV_8U, buffer);

    auto addable = shared_ptr<MyStruct>(new MyStruct())>;
    addable->matA = data.clone();
    lock_guard<mutex> guard(queueGuard);
    awaitingProcessing.push(addable);

    }
    线程 2(消费者):
        shared_ptr<MyStruct> pullFromQueue(){
    lock_guard<mutex> guard(queueGuard);
    if (awaitingProcessing.size() > 0){
    auto returnable = awaitingProcessing.front();
    awaitingProcessing.pop();
    return returnable;
    }
    return nullptr;
    }

    void threadLogic(){
    while (!interruptFlag){
    auto ptr = pullFromQueue();
    if (ptr == nullptr){
    usleep(5);
    }
    else{
    doSomething(ptr);
    }
    // ptr destructor called here, as refcount properly hits zero
    }

    }


    如果我没记错的话,std 数据集合通常不会释放它们的内存并将其保留为储备,以防大小再次增长。然而,这个集合(队列和/或列表)由指针组成,所以即使队列变大,内存占用也应该很小。
    我不熟悉 OpenCV 的内存管理,但它似乎在做类似的事情。暂停队列填充允许队列大小缩小,但内存不会缩小。然后,恢复填充会增加队列大小,而不会增加内存大小。

    总结几个关键点:
  • 内存确实在没有改变范围的情况下被释放(即不是内存泄漏)
  • 仅当队列大小为零时才释放内存。如果队列大小永远保持在 1
  • ,它将不会释放
  • 结构被破坏
  • 结构包含克隆的 cv::mats (我认为这是关键点)
  • 列表/队列只包含指针,因此应该很小
  • 最佳答案

    std::queue使用 std::deque默认为内部容器。当内存被释放时,在很大程度上定义了实现(当大小达到零时可能是这种情况),但是 std::dequestd::vector确实具有释放多余内存的功能,即 shrink_to_fit ( 功能)。 std::queue 没有此功能。接口(interface),但可以通过继承来完成(队列中的容器是 protected )。
    伪代码:

    template<class T>
    struct shrinkable_queue : public std::queue<T> {
    void shrink_to_fit() {c.shrink_to_fit();}
    };

    您也可以使用 std::queue<T, std::list<T>> .我确实检查了 MSVC 实现,因为您说您也尝试过 list 并且至少在我的版本中,即使删除单个节点(如预期的那样),它似乎也会释放内存。

    关于c++ - 为什么这个指向结构的指针的 std::queue/list 直到 List.Size() == 0 才释放内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62671148/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com