Priority_queue 问题 - 在堆之后写入内存

发布于 2024-08-09 21:15:09 字数 3365 浏览 11 评论 0原文

我正在尝试使用priority_queue,但程序不断失败,并显示错误消息“HEAP CORRUPTION DETECTED”。

以下是片段:

class CQueue { ...
              priority_queue<Message, deque<Message>, less<deque<Message>::value_type> > m_messages;
...};

类 Message 已重载运算符 >且<

在这里我填充队列:

CQueue & operator+=(Message &rhv)
{
    m_messages.push(rhv);  //This is where program fails
    return *this;
}

并在主程序中:

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
}

我不知道问题是什么。 在线失败

    push_heap(c.begin(), c.end(), comp);

当我推送大约 8 个项目时,就会发生这种情况,并且在 << 时 。队列>

:(

这是消息类的定义 - 非常简单:

#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 - 消息

I am trying to use priority_queue, and program constantly fails with error message 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 <

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

    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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖树树初阳… 2024-08-16 21:15:09

我认为问题在于您的 Message 对象保留了指向原始 C 字符串的指针,然后这些字符串被释放。在这些行中:

cin >> str;

Message p(str.c_str(), rand()%12);

在循环的每次迭代中,您都会向 str 读入一个新值,这会使它的 c_str() 方法返回的任何旧指针无效,因此您的旧消息指向无效数据。您应该更改 Message 对象,以便将其字符串存储为 std::string 而不是 char*。这将正确地将字符串复制到 Message 对象中。

或者,如果您无法更改 Message 类,则必须自己显式复制字符串,例如使用 strdup()malloc()< /code>/new[]+strcpy(),然后您必须记住在稍后的某个时刻取消分配字符串副本。

I think the problem is that your Message objects are keeping pointers to raw C strings which are then getting deallocated. 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. You should change your Message object so that it stores its string as an std::string instead of a char*. This will properly copy the string into the Message object.

Alternatively, if you can't change the Message class, you'll have to explicitly copy the string yourself, e.g. using strdup() or malloc()/new[]+strcpy(), and then you have to remember to deallocate the string copies at some later point.

极致的悲 2024-08-16 21:15:09

我不能让它失败。
但没有足够的信息来编译这一行:

push_heap(c.begin(), c.end(), comp);

但我看到的唯一问题是:

1)你有一个默认构造函数,可以创建一个具有 NULL 名称的 Poruka:

Poruka::Poruka():m_tekst(NULL), m_prioritet(-1){}

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);

注意:

  • 您可以通过使用 std::string 类使您的代码更加简单。
  • 如果您仍然想使用 char* 那么如果您保证它永远不会为 NULL 那么代码会更简单
  • 此外还有一个更简单的模式用于定义标准复制构造函数和赋值运算符。它被称为复制/交换idium。
  • 您不需要定义所有这些关系运算符。有一组自动工作的模板,请参见 http://www.sgi。 com/tech/stl/operators.html。你只需要定义operator< and 运算符==

这是复制/交换 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);
     }

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:

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:

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:

  • You could make your code much simpler by using the std::string class.
  • If you still want to use char* then if you gurantee it is never NULL then the code is simpler
  • Also there is a simpler patter for defining the standard copy constructor and assignment operator. It is refered to as the copy/swap idium.
  • You dont need to define all those relational operators. There is a set of template ones that work automatically in see http://www.sgi.com/tech/stl/operators.html. You just need to define operator< and operator==

Here is an example of the copy/swap 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);
     }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文