首页 > 解决方案 > 基本单生产者,单消费者队列。内存未释放

问题描述

我想实现一个基本的单一生产者,单一消费者 WorkerQueue。问题是,排队对象的内存没有被释放。

如果我

  1. 用 1000 个 1MB 大小的对象填充 WorkerQueue::queue_
  2. 调用 WorkerQueue::Start()

应用程序的内存使用量从 1GB 慢慢下降到零。

如果我

  1. 调用 WorkerQueue::Start();
  2. 用 1000 个 1MB 大小的对象填充 WorkerQueue::queue_

应用程序的内存使用量保持在 1GB 不变,直到程序退出。

在这两种情况下,所有数据包都被处理,并且数据包析构函数被调用 1000 次。因此,尽管 Packet 调用了析构函数,但内存似乎并没有被释放。当然,我希望能够在调用 ::Start() 后将项目排入队列。

平台:Ubuntu 18.10,g++-8

g++ -pthread -g -std=gnu++14 -o mytest main.cpp

#include <iostream>
#include <condition_variable>
#include <thread>
#include <vector>
#include <mutex>

using namespace std;

struct Packet {
    explicit Packet(size_t size) {
        data_.resize(size );
    }
    virtual ~Packet() {
        data_ = std::vector<char>();
        std::cout << "~Packet();\n";
    }
    std::vector<char> data_;
};

template<class T>
struct WorkerQueue {
    void Start() {
        t_ = std::move(thread{&WorkerQueue::Run, this});
    }

    void Enqueue(T t) {
        std::lock_guard<std::mutex> l{m_};
        queue_.push_back(std::move(t));
        cv_.notify_one();
    }

    void Run() {
        while(true) {
            {
                std::unique_lock<std::mutex> l{m_};
                cv_.wait(l, [&](){return !queue_.empty();});
                // calls T::~T()
                queue_.erase(begin(queue_));
                std::cout << "q_size: " << queue_.size() << endl;
            }
            // simulate workload
            this_thread::sleep_for(50ms);
        }
    }

    std::vector<T> queue_;
    thread t_;
    mutex m_;
    condition_variable cv_;
};


int main() {
    const size_t kPacketSize = 1*1000*1000;
    WorkerQueue<std::unique_ptr<Packet>> wq;

    wq.Start();// DOES NOT free memory
    for(int i=0;i<1000;++i) {
        wq.Enqueue(make_unique<Packet>(kPacketSize));
    }
//    wq.Start();// DOES free memory

    this_thread::sleep_for(60s);
}

标签: c++c++14

解决方案


推荐阅读