我正在编写一个查询处理器,它分配大量内存并尝试查找匹配的文档。每当我找到匹配项时,我都会创建一个结构来保存描述文档的两个变量并将其添加到优先级队列中。由于无法知道我将执行此操作的次数,因此我尝试使用new动态创建结构。当我从优先级队列中弹出一个struct时,队列(STL优先级队列实现)应该调用该对象的析构函数。我的结构代码没有析构函数,所以我假设在这种情况下调用默认的析构函数。
但是,我第一次尝试创建DOC结构时,出现以下错误:
QueryProcessor.exe中0x7c812afb处的未处理异常:Microsoft C ++异常:内存位置为0x0012f5dc的std :: bad_alloc ..
我不明白发生了什么 - 我耗尽了这么多内存以至于堆满了吗?这似乎不太可能。而且我之前甚至没有使用过那个指针。
所以:首先,我在做什么导致错误,其次,以下代码会不止一次工作?我是否需要为每个创建的结构指定一个单独的指针,或者我是否可以重复使用相同的临时指针并假设该队列将保留指向每个结构的指针?
这是我的代码:
struct DOC{
int docid;
double rank;
public:
DOC()
{
docid = 0;
rank = 0.0;
}
DOC(int num, double ranking)
{
docid = num;
rank = ranking;
}
bool operator>( const DOC & d ) const {
return rank > d.rank;
}
bool operator<( const DOC & d ) const {
return rank < d.rank;
}
};
//a lot of processing goes on here
priority_queue<DOC, std::vector<DOC>, std::greater<DOC>> q;
//when a matching document is found, I do this:
rank = calculateRanking(table, num);
//if the heap is not full, create a DOC struct with the docid and rank and add it to the heap
if(q.size() < 20)
{
doc = new DOC(num, rank);
q.push(*doc);
doc = NULL;
}
//if the heap is full, but the new rank is greater than the
//smallest element in the min heap, remove the current smallest element
//and add the new one to the heap
else if(rank > q.top().rank)
{
q.pop();
cout << "pushing doc on to queue" << endl;
doc = new DOC(num, rank);
q.push(*doc);
}
非常感谢,bsg。
答案 0 :(得分:4)
为什么要在堆上创建以下结构:
doc = new DOC(num, rank);
q.push(*doc);
首先在堆上创建DOC
,然后在队列中存储对象的副本,然后泄漏动态创建的DOC
。
以下就足够了,不会泄漏:
q.push(DOC(num, rank));
答案 1 :(得分:0)
当你执行q.pop()时,你需要释放你要弹出的指针,否则你就会泄漏。如果你有很多元素,这可能是你的问题。
Doc *p = q.front();
delete p;
q.pop();
正如其他人所提到的,如果你宣布你的队列保存Doc而不是Doc *,那么你不必自己管理内存,容器会为你做。
答案 2 :(得分:0)
关于异常:类bad_alloc
有一个成员函数what()
,它将const char *
返回给一个字符串,其中包含错误原因的可读描述。
编辑:如果您正在考虑存储动态分配的对象,请存储指针而不是对象的引用。
答案 3 :(得分:0)
你有内存泄漏。 STL容器的插入方法存储您传入的类型的副本,因此您不需要在堆上分配doc。
而不是
doc = new DOC(...)
q.push(*doc);
doc = NULL;
要么
doc(...);
q.push(doc);
或者
doc = new DOC(...);
q.push(*doc);
delete doc;
doc = NULL;