我有一个程序将指向包含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的内存管理,但它似乎在做类似的事情。暂停队列填充允许队列大小缩小,但内存不会缩小。然后,恢复填充会增加队列大小,而不会增加内存大小。
总结几点要点:
发布于 2020-07-01 08:13:00
默认情况下,std::queue
使用std::deque
作为内部容器。当内存被释放时,实现在很大程度上是定义的(当大小达到零时也是如此),但是std::deque
和std::vector
确实有一个释放多余内存的函数,即shrink_to_fit
(c++11功能)。这在std::queue
接口中是不可用的,但是可以通过继承来完成(队列中的容器是protected
)。
psudocode
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,至少在我的版本中,它似乎在删除单个节点时释放内存(正如预期的那样)。
https://stackoverflow.com/questions/62671148
复制相似问题