赛格。故障调整数组C ++

时间:2016-04-11 00:42:05

标签: c++ arrays resize fault

我有一个充满“作业”(名称+优先级)的优先级队列数组。如果它已满,我已经能够将所有与队列相关的工作放在重新调整大小之外。以下是我认为导致分段错误的位,这是我无法弄清楚的。

编辑:

这里有更多的代码可以编译,我留在其余的函数中,以防万一可能有所帮助。现在初始容量设置为5,当您尝试将作业添加到完整列表时,它将使阵列的容量加倍,并允许您在SEG之前添加更多作业。故障。

pq.h

#ifndef PQ_H
#define PQ_H
#include "interface.h"
#include <string>
using namespace std;

class Job {
    public:
        int getPriority();
        string getTaskName();
        void setPriority(int val);
        void setTaskName(string tname);
        Job();
    private:
        int priority;
        string taskName;
};

class PriorityQueue {

    public:
        PriorityQueue();
        ~PriorityQueue();
        int size();
        bool isEmpty();
        void clear();
        void enqueue(string value, int priority);
        string dequeue();
        string peek();
        int peekPriority();
        PriorityQueue(const PriorityQueue & src);
        PriorityQueue & operator=(const PriorityQueue & src);

    private:
        static const int INITIAL_CAPACITY = 5;  
        Job *array;
        int count;
        int capacity;

    void expandCapacity() {
        Job *oldArray = array;
        capacity *= 2;
        array = new Job[capacity];
        for (int i = 0; i < count; i++) {
            array[i] = oldArray[i];
        }
        delete[] oldArray;
    }
};

#endif

pq.cpp

#include <iostream>
#include <cstring>
using namespace std;
//#include "job.h"
#include "pq.h"

Job::Job() // Constructor
 {
    priority= 0;
    taskName = "There are no items in the list.";
}

int Job::getPriority(){ // returns the prority of the job
    return priority;
}
string Job::getTaskName(){ // returns the name of the job
    return taskName;
}
void Job::setPriority(int val){ // sets the priority of a newly created job
    priority = val;
}
void Job::setTaskName(string tname){ // sets the name of a new job
    taskName = tname;
}

PriorityQueue::PriorityQueue() // constructor
    {
        count = 0;
        capacity = INITIAL_CAPACITY - 1;
        array = new Job[INITIAL_CAPACITY];
        }

PriorityQueue::~PriorityQueue() { // destructor
   delete [] array;

}

int PriorityQueue::size() { // returns the number of jobs in the queue
   return count;  
}

bool PriorityQueue::isEmpty() { // returns true if queue is empty
   if (count != 0){
       return false;
   }else{
   return true;
   }
}

void PriorityQueue::clear() { // clears queue of all jobs
   count = 0;
   // need to make it remove and delete the items
}

void PriorityQueue::enqueue(string value, int priority) { 
   // tests size to see if Queue is a max capacity
   if(count == capacity){
       expandCapacity();
       cout << "\tList was full and has been expanded\n";
   }
   array[++count].setPriority(priority);
   array[count].setTaskName(value);

   // upheap operations
   Job v = array[count];
   int tempcount = count;
   while (array[tempcount/2].getPriority() >= v.getPriority()){
       array[tempcount] = array[tempcount/2];
       tempcount = tempcount/2;
   array[tempcount] = v;
   }

}
string PriorityQueue::dequeue() { 
    // removes the job with the highest priority from the queue and returns the name

    if(this->isEmpty()){ // make sure the queue isnt empty
        string empty = "The queue is empty";
        return empty;   
    }else{
   Job remove = array[1];
   array[1] = array[count--];

   int j;
   Job v;
   int k = 1;
   v = array[k];
   while(k <= count/2){
       cout << "dequeuewhile"; //  test
       j = k + k;
       if(j < count && array[j].getPriority() > array[j+1].getPriority()){
           j++;
           cout << "dequeueloop if1"; // test
       }
       if(v.getPriority() <= array[j].getPriority()){
           cout << "dequeueloop if2"; //test
           break;
       }
       array[k] = array[j];
       k = j;
   }
   array[k] = v;

   return remove.getTaskName(); //  returns the name of the removed job
    }
}
string PriorityQueue::peek() { // returns the name of the highest priority job without removing it from the queue
    if(count == 0){
        return array[0].getTaskName();
    }
   return array[1].getTaskName();
}

int PriorityQueue::peekPriority() { // returns the priority from the highest priority job without removing it from the queue
        if(count == 0){
        cout << "\tThere are no items in the list.\n";
        return array[0].getPriority();
    }
   return array[1].getPriority();
}

2 个答案:

答案 0 :(得分:1)

我认为当你执行++count时,count的下一次使用将超出数组范围。

array[++count].setPriority(priority);
// SEGMENTATION FAULT HERE
array[count].setTaskName(value); 

如果数组的容量为5,count为4,那么您只需将count增加到5,并尝试访问超出范围的元素5。

 array = new Job[capacity];
 for (int i = 0; i < count; i++) {
     array[i] = oldArray[i];
 }

假设capacity为10,所以你有一个包含10个元素的数组,范围从0到9。 count告诉我们正在使用多少元素。 如果count恰好是9,那么当您将count增加1时,它现在是10。然后,当你标记为产生段故障时,你试图访问元素10,在我们的例子中。长度为10的数组中没有元素10,因此您已超出范围。

array[++count].setPriority(priority); // array[10], but last element is 9!
// SEGMENTATION FAULT HERE
array[count].setTaskName(value); // array[10], but last element is 9!

当然,在继续使用array[count]之后,该部分之后的所有内容都会导致同样的问题。

答案 1 :(得分:0)

您的原始代码与@antiHUMAN给出的上一个答案完全相同。

您遇到的问题是混合或错误地使用基于0和基于1的概念。

你的第一个错误是让capacity为0。 capacity应表示数组中的最大项数,因此不应从中减去1。如果数组可容纳5个项目,则capacity应为5,而不是4。

PriorityQueue::PriorityQueue() // constructor
{
    count = 0;
    capacity = INITIAL_CAPACITY;  // this remains 1-based.
    array = new Job[INITIAL_CAPACITY];
}

或使用initializer-list:

PriorityQueue::PriorityQueue() : count(0), 
                                 capacity(INITIAL_CAPACITY), 
                                 array(new Job[INITIAL_CAPACITY]) {}

您的情况中基于0的数字应为count,而不是capacity。鉴于此,由于count从0开始,capacity从1开始,因此需要更改enqueue中的测试:

   if(count + 1 == capacity){
        expandCapacity();
        cout << "\tList was full and has been expanded\n";
    }

请注意,为了说明count从0开始且capacity基于1这一事实,我需要添加1来计算。