[英]Problem with priority_queue - Writing memory after heap
I am trying to use priority_queue, and program constantly fails with error message HEAP CORRUPTION DETECTED. 我正在尝试使用priority_queue,并且程序不断失败,并显示错误消息HEAP CORRUPTION DETECTED。
here are the snippets: 以下是片段:
class CQueue { ...
priority_queue<Message, deque<Message>, less<deque<Message>::value_type> > m_messages;
...};
class Message has overloaded operators > and < 类Message具有重载的运算符>和<
Here I fill up queue: 在这里,我填满队列:
CQueue & operator+=(Message &rhv)
{
m_messages.push(rhv); //This is where program fails
return *this;
}
and in the main program: 在主程序中:
string str;
CQueue pq;
for(int i = 0; i < 12; ++i)
{
cin >> str;
Message p(str.c_str(), rand()%12); //Create message with random priority
pq += p; //add it to queue
}
I have no idea what seems to be the problem. 我不知道这是什么问题。 It happens when I push about 8 items, and it fails on line
当我推送约8个项目时,它会发生,并且在线失败
push_heap(c.begin(), c.end(), comp);
in < queue > 在<队列>中
:( :(
Here is the definition of message class - it's very simple: 这是消息类的定义-非常简单:
#pragma once
#include <iostream>
#include <cstring>
#include <utility>
using namespace std;
class Poruka
{
private:
char *m_tekst;
int m_prioritet;
public:
Poruka():m_tekst(NULL), m_prioritet(-1){}
Poruka(const char* tekst, const int prioritet)
{
if(NULL != tekst)
{
// try{
m_tekst = new char[strlen(tekst) + 1];
//}
//catch(bad_alloc&)
// {
// throw;
// }
strcpy(m_tekst, tekst);
}
else
{
// try
// {
m_tekst = new char[1];
// }
// catch(bad_alloc&)
// {
// throw;
// }
m_tekst[0] = '\0';
}
m_prioritet = prioritet;
}
Poruka(const Poruka &p)
{
if(p.m_tekst != NULL)
{
//try
//{
m_tekst = new char[strlen(p.m_tekst) + 1];
//}
//catch(bad_alloc&)
//{
// throw;
//}
strcpy(m_tekst, p.m_tekst);
}
else
{
m_tekst = NULL;
}
m_prioritet = p.m_prioritet;
}
~Poruka()
{
delete [] m_tekst;
}
Poruka& operator=(const Poruka& rhv)
{
if(&rhv != this)
{
if(m_tekst != NULL)
delete [] m_tekst;
// try
//{
m_tekst = new char[strlen(rhv.m_tekst + 1)];
//}
//catch(bad_alloc&)
//{
// throw;
//}
strcpy(m_tekst, rhv.m_tekst);
m_prioritet = rhv.m_prioritet;
}
return *this;
}
friend ostream& operator<<(ostream& it, const Poruka &p)
{
it << '[' << p.m_tekst << ']' << p.m_prioritet;
return it;
}
//Relacioni operatori
friend inline bool operator<(const Poruka& p1, const Poruka& p2)
{
return p1.m_prioritet < p2.m_prioritet;
}
friend inline bool operator>(const Poruka& p1, const Poruka& p2)
{
return p2 < p1;
}
friend inline bool operator>=(const Poruka& p1, const Poruka& p2)
{
return !(p1 < p2);
}
friend inline bool operator<=(const Poruka& p1, const Poruka& p2)
{
return !(p1 > p2);
}
friend inline bool operator==(const Poruka& p1, const Poruka& p2)
{
return (!(p1 < p2) && !(p2 < p1));
}
friend inline bool operator!=(const Poruka& p1, const Poruka& p2)
{
return (p1 < p2) || (p2 < p1);
}
}; };
Poruka - Message Poruka-消息
I think the problem is that your Message
objects are keeping pointers to raw C strings which are then getting deallocated. 我认为问题在于您的
Message
对象正在保留指向原始C字符串的指针,然后将其释放。 In these lines: 在这些行中:
cin >> str;
Message p(str.c_str(), rand()%12);
On each iteration of the loop, you're reading in a new value to str
, which invalidates any old pointers returned by its c_str()
method, so your older messages are pointing to invalid data. 在循环的每次迭代中,您都将读取一个新值
str
,该值会使c_str()
方法返回的所有旧指针无效,因此您的旧消息将指向无效数据。 You should change your Message
object so that it stores its string as an std::string
instead of a char*
. 您应该更改
Message
对象,以便将其字符串存储为std::string
而不是char*
。 This will properly copy the string into the Message
object. 这样可以将字符串正确复制到
Message
对象中。
Alternatively, if you can't change the Message
class, you'll have to explicitly copy the string yourself, eg using strdup()
or malloc()
/ new[]
+ strcpy()
, and then you have to remember to deallocate the string copies at some later point. 另外,如果您不能更改
Message
类,则必须自己显式复制该字符串,例如,使用strdup()
或malloc()
/ new[]
+ strcpy()
,然后必须记得取消分配该字符串。在以后的某个时间点复制字符串。
I can't get it to fail. 我不能让它失败。
But there is not enough info to compile this line: 但是没有足够的信息来编译此行:
push_heap(c.begin(), c.end(), comp);
But the only problems I see are: 但是我看到的唯一问题是:
1) You have a default constructor that could create a Poruka with a NULL name: 1)您有一个默认构造函数,可以使用NULL名称创建一个Poruka:
Poruka::Poruka():m_tekst(NULL), m_prioritet(-1){}
2) Not a problem because you test for it most places but in the assignment operator you miss a test: 2)没问题,因为您测试了大多数地方,但是在赋值运算符中却错过了一个测试:
Poruka::Poruka& operator=(const Poruka& rhv)
{
....
// There was no test for 'rhv.m_tekst' being NULL here.
//
m_tekst = new char[strlen(rhv.m_tekst + 1)];
strcpy(m_tekst, rhv.m_tekst);
Notes: 笔记:
Here is an example of the copy/swap idium 这是复制/交换idium的示例
class X
{
X(X const& copy)
{
// Do the work of copying the object
m_tekst = new char[strlen(copy.m_tekst) + 1];
...
m_prioritet = copy.m_prioritet;
}
X& operator=(X const& copy)
{
// I like the explicit copy as it is easier to read
// than the implicit copy used by some people (not mentioning names litb)
//
X tmp(copy); // Use the copy constructor to do the work
swap(tmp);
}
void swap(X& rhs) throws ()
{
std::swap(this->m_tekst, rhs.m_tekst);
std::swap(this->prioritet, rhs.prioritet);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.