在一些名为Tasks.h的文件中,我具有以下功能:-
void source_thread_func(BlockingQueue<Task> &bq, int num_ints)
{
std::cout<<"On source thread func"<<std::endl; // Debug
for (int i = 1; i <= num_ints; i++)
{
//Valgrind does not like this
std::unique_ptr<Task> task(new Task(i, i == num_ints));
std::cout<<"Pushing value = "<<i<<std::endl; // Debug
bq.push(task);
Task* tp = task.release();
assert (task.get() == nullptr);
delete tp;
}
}
并且BlockingQueue中的相关推送功能为
void push(std::unique_ptr<T>& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(std::move(item));
mlock.unlock();
cond_.notify_one();
}
但是,这在与Valgrind进行检查时仍会导致泄漏。你能告诉我泄漏在哪里吗?我附上valgrind结果的屏幕截图。我还可以删除该指针吗?
编辑:任务不包含副本构造函数(我已将其删除)
//Tasks.h
namespace threadsx
{
class Task
{
public:
Task(int val, bool sentinel = false)
{
m_val = val;
Sent = sentinel;
}
int m_val;
int Sent;
//disable copying
Task (const Task&) = delete;
};
void source_thread_func(BlockingQueue<Task> &bq, int num_ints)
{
std::cout<<"On source thread func"<<std::endl; // Debug
for (int i = 1; i <= num_ints; i++)
{
std::unique_ptr<Task> task(new Task(i, i == num_ints));
std::cout<<"Pushing value = "<<i<<std::endl; // Debug
bq.push(task);
Task* tp = task.release();
assert (task.get() == nullptr);
delete tp;
}
}
}
++++++++++++++++++++++++++++++++
///BlockingQueue.h
namespace threadsx
{
// -- Custom Blocking Q
template <typename T>
class BlockingQueue
{
private:
std::queue<std::unique_ptr<T>> queue_;
std::mutex mutex_;
std::condition_variable cond_;
void push(std::unique_ptr<T>& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(std::move(item));
mlock.unlock();
cond_.notify_one();
}
BlockingQueue()=default;
BlockingQueue(const BlockingQueue&) = delete; // disable copying
BlockingQueue& operator=(const BlockingQueue&) = delete; // disable assignment
};
}
++++++++++++++++++++++++++++++++
//main.cpp
int main(int argc, char **argv)
{
int num_ints = 30;
int threshold = 5;
threadsx::BlockingQueue<threadsx::Task> q;
std::vector<int> t;
std::thread source_thread(threadsx::source_thread_func, std::ref(q), num_ints);
if(source_thread.joinable())
source_thread.join();
return 0;
}
答案 0 :(得分:2)
您显示的程序没有delete
分配的Task
。 push
将所有权从task
移开,因此tp
始终为空。
资源所有权已转移到queue_
中,并且示例程序中未显示该指针如何泄漏(假设valgrind是正确的)。
一些质量问题:
正如注释中指出的那样,通过非const引用传递唯一指针通常是一个糟糕的设计。当您打算转让所有权时,按值传递。
我已删除Task上的副本构造函数。按价值传递仍然有效吗?
Task
是否可复制与唯一指针是否可以按值传递无关。唯一指针是可移动的,与指向对象的类型无关,因此可以按值传递。
不要为了删除内存而从唯一指针释放。只需让唯一指针超出范围即可-它的析构函数负责删除。
答案 1 :(得分:0)
由于所有权已不再是您的所有权,因此您无法删除该原始任务。
autoStartup=true
阻止队列:
void source_thread_func(BlockingQueue<Task>& bq, int num_ints)
{
std::cout<<"On source thread func"<<std::endl; // Debug
for (int i = 1; i <= num_ints; i++)
{
std::unique_ptr<Task> task = std::make_unique<Task>(i, i == num_ints);
bq.push(std::move(task));
}
}
如果您想避免std :: move的麻烦,请改用shared_ptr