在一些名为 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中的相关push函数是
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;
}
最佳答案
您显示的程序不会删除
分配的Task
。 push
将所有权从 task
移开,因此 tp
始终为 null。
资源的所有权转移到 queue_
中,示例程序中没有显示该指针是如何泄漏的(假设 valgrind 是正确的)。
一些质量问题:
正如评论中所指出的,通过非常量引用传递唯一指针通常是一种糟糕的设计。当您打算转让所有权时按值(value)传递。
I've deleted the copy constructor on Task. Would passing by value still work?
Task
是否可复制与唯一指针是否可以按值传递无关。 Unique指针无论被指向的对象是什么类型都是可移动的,因此可以按值传递。不要仅仅为了删除内存而释放唯一指针。只需让唯一指针超出范围 - 它的析构函数负责删除。
关于c++ - 即使在释放指针后,Valgrind 仍显示 Leak_DefinitelyLost,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55003606/