0

テンプレート化されたキューのデキュー関数は、文字列のキューに対しては正常に機能しますが、カスタム ロボット クラスを使用すると、ポインターを削除しようとするとクラッシュします。その理由が気になります。

たとえば、main.cpp では

#include <iostream>
#include <cstdlib>
#include <cstring>
#include "robotqueue.h"
#include "robotcustomer.h"
#include "servicestation.h"

using namespace std;

int main()
{
    //- TEST ONE: QUEUE<STRING> -//
    RobotQueue < string > stringQueue;
    string a("Tim");
    string b("Greg");

    stringQueue.enqueue(a);
    stringQueue.enqueue(b);
    stringQueue.dequeue();
    stringQueue.dequeue();

    //- TEST TWO: QUEUE<RobotCustomer> -//
    RobotQueue < RobotCustomer > robotQueue;
    RobotCustomer e("Tim",3);
    RobotCustomer f("Greg",5);

    robotQueue.enqueue(e);
    robotQueue.enqueue(f);
    robotQueue.dequeue();            <--- Segfault occurs here
    robotQueue.dequeue();
    return 0;
}

文字列キューは正常に機能しますが、次のエラーが発生します。

***Error in `q': munmap_chunk(): invalid pointer: 0x0000000001d6c108 ***
Aborted (core dumped)

私のテンプレート化されたキューはこのようなものです (これがもっと必要かどうかはわかりません)。

robotqueue.hpp

// Default Constructor
template <typename T>
RobotQueue<T>::RobotQueue()
{
    m_size = 0;
    m_front = NULL;
    m_back = NULL;
}
// Default destructor
template <typename T>
RobotQueue<T>::~RobotQueue() 
{
    Node<T>* currNode = m_front, *nextNode = NULL;
    while ( currNode != NULL )
    {
        nextNode = currNode->m_next;
        delete currNode;
        currNode = nextNode;
    }
    m_size = 0;
}

template <typename T>
void RobotQueue<T>::enqueue(const T& x)
{
    Node<T> *newNode = new Node<T>;
    newNode->m_data = x;
    newNode->m_next = NULL;
    if(m_front == NULL)
        m_front = newNode;
    else
        m_back->m_next = newNode;
    m_back = newNode;
    m_size++;                           // Increments queue size
    return;
}

template <typename T>
void RobotQueue<T>::dequeue()
{
    Node<T>* tempNode = new Node<T>;
    if(m_front == NULL)
        cout << "dequeue error: Queue is empty" << endl;
    else
    {
        tempNode = m_front;
        m_front = m_front->m_next;
        delete tempNode;     <-- Segfault occurs here in RobotCustomer class
        m_size--;                       // Increments queue size
    }
    return;
}

RobotCustomer がクラスであるため、 m_data がそれを指すことができないなどと関係があると思いますか? ここでは専門家ではありません:p

RobotCustomer.h

/* ------------------  Class RobotCustomer ------------------ */
class RobotCustomer
{
private:
  string m_name;                // Name of Robot
  string* m_reqServices;        // Array of services requeseted
  int m_numServices;            // Number of services requested
  int m_currService;            // Number of services compelted
  bool m_busy;                  // Logic for if robot is in line/servicing
  bool m_done;                  // Logic for if robot is done
public:
  //- functions and such that I don't think affect the queue -//

御時間ありがとうございます :)

---------------------UPDATED_WITH コンストラクター/デコンストラクター-------------------

RobotCustomer.cpp

// Default Constructor
RobotCustomer::RobotCustomer()
{
    m_name = "";
    m_numServices = 0;
    m_currService = 0;
    m_busy = false;
    m_done = false;
}
// Overloaded Constructor
RobotCustomer::RobotCustomer(string n, int x)
{
   m_name = n;
   m_numServices = x;
   m_reqServices = new string[m_numServices]; 
   m_currService = 0;
   m_busy = false;
   m_done = false;
}

// Default Destructor
RobotCustomer::~RobotCustomer()
{
    delete m_reqServices;
}
4

1 に答える 1

0

関数のいくつかの行を見てみましょう。

Node<T>* tempNode = new Node<T>;
tempNode = m_front;
delete tempNode;

最初にメモリを割り当て、そのポインタをtempNode変数に割り当てます。次に、その変数を別のメモリを指すように再割り当てし、元のポインターを失います。次に、割り当てた元のメモリではなくなったメモリを解放しようとします。

これでクラッシュが発生することはありませんが (私が見る限り)、メモリ リークです。


クラッシュの原因についての私の推測は、メンバーRobotCustomerに対して、おそらくコンストラクターでメモリを動的に割り当てることです。m_reqServicesただし、コピー コンストラクターまたはコピー代入演算子を実装しない場合、またはそれらの関数でポインターの浅いコピーを行うだけの場合は、代入を使用して

newNode->m_data = x

enqueue関数では、同じポインターを持つ2つのオブジェクトがあり、そのうちの 1 つが削除されると、そのデストラクタが割り当てられたメモリを削除し、他のオブジェクトのポインターが未割り当てのメモリを指すようになり、再度解放しようとすると未定義の動作が発生します。

3、5 、およびゼロのルールについて読む必要があります。std::vectoror std::array(該当する場合)を使用し、ゼロの規則に従うことをお勧めします。

もちろん、標準コンテナを使用するという話になると、なぜ最初から使用しないのだろうかstd::queue?

于 2016-04-06T15:03:55.220 に答える