2012-04-12 25 views
0

私のプログラムでポインタの配列へのポインタの割り当てに問題があります。関数が引数としてポインタを受け入れ、そのポインタを配列のインデックスに割り当てようとしました。それはうまくコンパイルされますが、実行されません、私はsegfaultを取得します。抽象クラスへのポインタの配列

エラーは、関数の最初の行であるEventHeap :: pushから発生します。

皆さんにご意見はありますか?

私は助けていただきありがとうございます。

編集:私は右のダウン下記の特定の問題を投稿しますが、私はちょうどそれ以下の場合には、コードを残しておきます:D

セグメンテーション違反がプッシュ機能、最初の行で発生します。

void ModemSimV2::nextCall(int delta){ 
    static int nextCallTime = 0; 
    static int userNum = 0; 

    Event *e; 
    e = new Dialin(userNum++, nextCallTime); 
    eventSet->push(e); 
    nextCallTime += delta; 
} 


//push function takes a pointer to an Event and puts into the array 
void EventHeap::push(Event *e) { 

    array[size] = e; 
    reIndex(size); 
    size++; 
} 

出典:

// ModemSimV2.cpp 
// 
// @author David Harrigan 
//   dtk24 
// 
// 4/10/2012 
// 
#include "ModemSimV2.h" 
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++ 

// Constructor for ModemSim. 
ModemSimV2::ModemSimV2(int modems, double avgLen, int callIntrvl) 
: freeModems(modems), avgCallLen(avgLen), 
freqOfCalls(callIntrvl), r((int) time(0)) 
{ 
    nextCall(freqOfCalls); // Schedule first call 
} 

// Place a new DIAL_IN event into the event queue. 
// Then advance the time when next DIAL_IN event will occur. 
// In practice, we would use a random number to set the time. 
void ModemSimV2::nextCall(int delta){ 
    static int nextCallTime = 0; 
    static int userNum = 0; 

    Event *e; 
    e = new Dialin(userNum++, nextCallTime); 
    eventSet->push(e); 
    nextCallTime += delta; 
} 

// Run the simulation until stopping time occurs. 
void ModemSimV2::runSim(int stoppingTime){ 
    Event *e; 
    int i = 0; 
    while(! eventSet->empty()){ 
     e = eventSet->pop(); 
     if (e->getTime() > stoppingTime) 
      break; 

     if (e->process(*this)) 
      eventSet->push(e); 

     nextCall(freqOfCalls); 
     i++; 
    } 
} 
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++ 

//Constructor for event 
Event::Event(){ 

} 

//copy constructor 
Event::Event(const Event &e) { 
    *this = e; 
} 

//virtual destructor 
Event::~Event() { 

} 

//operator overloads 
bool Event::operator > (const Event & rhs) const { 
    return time > rhs.time; 
} 

bool Event::operator < (const Event & rhs) const { 
    return time < rhs.time; 
} 

bool Event::operator <= (const Event & rhs) const { 
    return time < rhs.time; 
} 

bool Event::operator != (const Event & rhs) const { 
    return time != rhs.time; 
} 

//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//+++++++++++++++++++++++++++++ Dialin +++++++++++++++++++++++++++++ 

//inhereited constructor 
Dialin::Dialin (int name, int tm) 
: time(tm), who(name) { 
    return; 
} 

//copy constructor 
Dialin::Dialin (const Dialin &d) { 
    *this = d; 
} 

//destructor 
Dialin::~Dialin() { 

} 

//bool process - unfinished 
bool Dialin::process(ModemSimV2 &m) { 
    cout << "User " << who << " dials in at time " 
    << time << endl; 

    if(m.freeModems > 0) { 
     m.freeModems--; 
     int howLong = r.negExp(m.avgCallLen); 
     cout << " and connects for " << howLong << 
     " minutes " << endl; 
     time += howLong; 
     return true; 
    } 
    else { 
     cout << "but gets busy signal" << endl; 
     return false; 
    } 
} 

//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//++++++++++++++++++++++++++++ Hangup +++++++++++++++++++++++++++++ 

//inhereited constructor 
Hangup::Hangup (int name, int tm) 
: time(tm), who(name) { 
    return; 
} 

//copy constructor 
Hangup::Hangup (const Hangup &h) { 
    *this = h; 
} 

//destructor 
Hangup::~Hangup () { 

} 

//bool process - unfinished 
bool Hangup::process(ModemSimV2 &m) { 

    m.freeModems++; 

    cout << "User " << who << " hangs up at time " 
    << time << endl; 

    return false; 

} 
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++ 

//EventHeap constructor 
EventHeap::EventHeap() { 

    array = new Event*[1]; 
    size = 0; 
} 

//constructor 
EventHeap::EventHeap(int numVals) { 

    array = new Event*[numVals]; 
    size = 0; 
} 

//push function takes a pointer to an Event and puts into the array 
void EventHeap::push(Event *e) { 

    array[size] = e; 
    reIndex(size); 
    size++; 
} 

//since this is a min-heap, it removes the smallest value in the array 
Event* EventHeap::pop() { 

    Event *e = array[0]; 
    array[0] = array[size - 1]; 
    size--; 
    if(!empty()) 
     buildHeap(0); 

    return e; 
} 

//builds the heap once popped, to reorder the array 
// 
void EventHeap::buildHeap(int index) { 

    int min; 

    if (getRight(index) >= size) { 
     if (getLeft(index) >= size) 
      return; 
     else 
      min = getLeft(index); 
    } 
    else { 
     if (array[getLeft(index)] <= array[getRight(index)]) 
      min = getLeft(index); 
     else 
      min = getRight(index); 
    } 
    if (array[index] != 0 && array[index] > array[min]) { 
     Event *temp(array[min]); 
     array[min] = array[index]; 
     array[index] = temp; 
     buildHeap(min); 
    } 
} 


//similar to buildHeap, but is called when a value is pushed to the array 
// 
void EventHeap::reIndex(int hole) { 

    while(array[hole] != NULL && array[hole] < array[getParent(hole)]) { 
     int pIndex = getParent(hole); 
     Event *temp(array[hole]); 
     array[hole] = array[pIndex]; 
     array[pIndex] = temp; 
     hole = pIndex; 
    } 
} 

//returns true if empty 
bool EventHeap::empty() const { 
    return (size == 0); 
} 

//returns the left child 
int EventHeap::getLeft(int index) const { 
    return (index * 2) + 1; 
} 

//returns the right child 
int EventHeap::getRight(int index) const { 
    return (index * 2) + 2; 
} 

//returns the parent 
int EventHeap::getParent(int index) const { 
    return (index - 1)/2; 
} 

ヘッダー:

// ModemSimV2.h 
// 
// @author David Harrigan 
//   dtk24 
// 
// 4/10/2012 
// 

#ifndef MODEM_SIM_V2_H 
#define MODEM_SIM_V2_H 

#include <queue> 
#include <vector> 
#include <functional> // for greater() 
#include <climits>  // for INT_MAX 
#include <iostream> 
#include "random.h" 

using namespace std; 
//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//++++++++++++++++++++++++++ ModemSimV2 +++++++++++++++++++++++++++ 
class EventHeap; 

class ModemSimV2 { 

public: 
    ModemSimV2(int modems, double avgLen, int callIntrvl); 
    // Add a call to eventSet at the current time, 
    // and schedule one for delta in the future. 
    void nextCall(int delta); 

    // Run the simulation 
    void runSim(int stoppingTime);// = INT_MAX); 

    friend class Event; 
    friend class Dialin; 
    friend class Hangup; 

private: 
    Random r;      // A random source 
    EventHeap *eventSet;     // Pending events 

    // Basic parameters of the simulation 
    int freeModems;     // Number of modems unused 
    const double avgCallLen;  // Length of a call 
    const int freqOfCalls;   // Interval between calls 
}; 


//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//+++++++++++++++++++++++++++++ Event +++++++++++++++++++++++++++++ 

class Event{ 

protected: 
    int who;  // the number of the user 
    int time;  // when the event will occur 

    friend class ModemSimV2; 

    Random r; 

public: 
    Event(); 
    Event(const Event &e); 
    virtual ~Event(); 

    bool operator > (const Event & rhs) const; 
    bool operator < (const Event & rhs) const; 
    bool operator <= (const Event & rhs) const; 
    bool operator != (const Event & rhs) const; 

    int getTime() { return time; }; 

    virtual bool process(ModemSimV2 &m) = 0; 
}; 

//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//+++++++++++++++++++++++++++++ Dialin ++++++++++++++++++++++++++++ 
class Dialin : public Event { 
public: 
    Dialin(int name = 0, int tm = 0); 
    Dialin(const Dialin &d); 
    ~Dialin(); 

    virtual bool process(ModemSimV2 &m); 

private: 
    int who; 
    int time; 
}; 

//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//+++++++++++++++++++++++++++++ Hangup ++++++++++++++++++++++++++++ 
class Hangup : public Event { 
public: 
    Hangup(int name = 0, int tm = 0); 
    Hangup(const Hangup &h); 
    ~Hangup(); 

    virtual bool process(ModemSimV2 &m); 

private: 
    int who; 
    int time; 
}; 

//xvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvxvx 
//++++++++++++++++++++++++++ EventHeap ++++++++++++++++++++++++++++ 

class EventHeap{ 

public: 
    EventHeap(); 
    EventHeap(int numIndex); 

    bool empty() const; 
    const int & findMin() const; 

    void push(Event *x); 
    Event * pop(); 

private: 
    int size;   // Number of elements in heap 
    Event **array;   // The heap array 

    void buildHeap(int index); 
    void reIndex(int hole); 
    int getLeft(int index) const; 
    int getRight(int index)const; 
    int getParent(int index)const; 
}; 
#endif 
+0

ここに掲載されているものよりも大幅に小さな問題に絞り込んでいるような音...問題をより簡単に見つけるために、小さな独立型の例を反映するために質問を更新できますか? – tmpearce

答えて

1

ここでは手掛かりです:

e = new Dialin(userNum++, nextCallTime); 
eventSet->push(*e); 

あなたは新しいオブジェクトを割り当て、そのコピーを推進しています。

もう一つの手がかり:

// Constructor for ModemSim. 
ModemSimV2::ModemSimV2(int modems, double avgLen, int callIntrvl) 
: 
    r((int) time(0)), 
    // what about eventSet? 
    freeModems(modems), 
    avgCallLen(avgLen), 
    freqOfCalls(callIntrvl), 
{ 
    nextCall(freqOfCalls); // Schedule first call 
} 
+0

プッシュ機能では、オブジェクトへの参照を受け入れる必要がありますか?プッシュプッシュをポインタの配列にプッシュします。 – dajee

+0

私はeventSet-> push(e)を実行しました。これはポインタeをプッシュし、次に配列[size] = e; EventHeapの配列にポインタeを代入する必要がありますか? – dajee

+0

@David:そうです。 –

0

eventSetは、しかし、あなたは、コンストラクタでそれを初期化しない、ModemSimV2EventHeap*として宣言されています。したがって、最初に使用すると、segfaultが発生します。

ModemSimV2::ModemSimV2(int modems, double avgLen, int callIntrvl) 
: freeModems(modems), avgCallLen(avgLen), 
freqOfCalls(callIntrvl), r((int) time(0)) 
{ 
    eventSet = new EventHeap(); // <-- missing this initialization 

    nextCall(freqOfCalls); // Schedule first call 
} 

また、メモリリークを回避するために、割り当てたメモリを解放するには、ModemSimV2とEventHeapにデストラクタが必要です。