3

大学のコースで行っている課題の一環として、CPUスケジューリングシミュレーターをC(C ++ではなく)で作成する必要があります。GCCでコンパイルするときに、「不完全な型へのポインターの逆参照」に関するいくつかのエラーが発生するという問題が発生しています。すべてのエラーは同じコードの結果であるため、そのコードに問題があると思います。

問題のあるコードは次のとおりです。

//Push a record of this state change to the back of the simulation's history list
listPushBack(sim->history, (void*)newRecord(p->pid, sim->currentTime, wait, ready));

これは、後で分析するためにシミュレーションの履歴を追跡することに関連しています。レコードは次のように定義されます。

//History.h

typedef struct record* Record;

//History.c

typedef struct record recordType;

struct record{
    long time;
    int pid;
    State oldState;
    State newState;
};

Record newRecord(int pid, long time, ProcessState oldState, ProcessState newState){
    Record r = (Record)malloc(sizeof(recordType));
    if(r == NULL){
        fprintf(stderr, "History.c:newRecord:Failed to allocate memory for new Record\n");
        //This is serious, abort execution
        exit(-1)
    }
    r->time = time;
    r->pid = pid;
    r->oldState = oldState;
    r->newState = newState;
    return r;
}

ここで、ProcessStateは次のように定義されます。

//Process.h

typedef enum process_state ProcessState;

enum process_state{
    arrive = 0,
    ready = 1,
    run = 2,
    wait = 3,
    done = 4
};

私は遊んで、これで同じエラーが発生しました:

Process p = (Process)listGetAt(sim->waitingQueue, i);
ProcessState old = p->state;
listPushBack(sim->history, (void*)newRecord(p->pid, sim->currentTime, old, p->state));

ありがたいことに、これはもう1週間の予定ではないので、遊ぶ時間はありますが、物事をいじるのに多くの時間を無駄にする前に、誰かが私を正しい方向に向けてくれることを望んでいます。

編集:コメントに表示される順序で質問に答える、

//DoubleLinkList.c

bool listPushBack(DoubleList l, void* data){
    return listInsert(l, data, -1);
}
bool listInsert(DoubleList l, void* data, int pos){
    int index = pos;
    //If value is negative, convert to a index relative to the end of the list
    if(index < 0){
        index = listSize(l) + index + 1;
    }
    //Check index bounds
    if(index > listSize(l) || index < 0){
        fprintf(stderr, "DoubleLinkList.c:listInsert:Insert index %i out of bounds\n", pos);
        //This is not serious enough to warrent an abort
        return false;
    }
    //Data is null
    if(data == NULL){
        fprintf(stderr, "DoubleLinkList.c:listInsert:Data value for doubly linked list node cannot be NULL\n");
        //This is not serious enough to warrent an abort
        return false;
    }
    Node insertNode = newNode(data);
    //Case: End of list
    if(index == listSize(l)){
        l->tail->next = insertNode;
        insertNode->prev = l->tail;
        l->tail = insertNode;
        l->size++;
        return true;
    }
    //Case: Start of list
    else if(index == 0){
        l->head->prev = insertNode;
        insertNode->next = l->head;
        l->head = insertNode;
        l->size++;
        return true;
    }
    //Case: Middle of list
    Node node = l->head;
    //Scan through list to reach index pos
    int i;
    for(i = 0; i < index; i++){
        if(node == NULL){
            fprintf(stderr, "DoubleLinkList.c:listGetPosition:NULL encoutered unexpectedly while traversing doubly linked list at index %i\n", i);
            //This is a serious problem, abort execution
            exit(-1);
        }
        node = node->next;
    }
    //Insert before Node at index pos
    insertNode->next = node;
    insertNode->prev = node->prev;
    node->prev->next = insertNode;
    node->prev = insertNode;
    l->size++;
    return true;
}

はい、プロセスは次のとおりです。

typedef process_Struct* Process

シミュレーション宣言:

//Simulation.c
struct simulation{
    SimType type;
    long currentTime;
    unsigned int totalProcesses;
    DoubleList arriveQueue;
    DoubleList readyQueue;
    DoubleList waitingQueue;
    DoubleList doneQueue;
    Process running;
    DoubleList history;
};

問題を投げているメソッドはrunSimulation(Simulation sim)です。ここで:

typedef simulation* Simulation;

runSimulationはSimulation.cで宣言されています

正確なエラーメッセージは次のとおりです。source/Simulation.c:154:50:エラー:不完全な型へのポインタの逆参照これが非常に煩わしいことを証明している理由です。-verbose、-g、および他のいくつかのデバッグフラグ。

私はtypdefポインターを使うべきではないことを理解していますが、愚かなことに、教授はそれを割り当ての要件にしました。引用:「可能であれば、typedefを使用して構造体へのポインターを定義します。これにより、TAがシミュレーションコードを読みやすくなります。」これはひどい考えであり、TAがコードを読み取れるはずなので、私はこれに非常に悩まされています。

4

3 に答える 3

2

通常、このエラーは、前方宣言されたものだけを使用して使用する場合に発生します。IEお持ちの場合:

 // foo.h
 struct Process; 

 // foo.c
 #include "foo.h"
 Process* foo;
 std::cout << foo->i

不完全な型のポインタの参照解除についてエラーが発生します。これは、この行でp/simを間接参照しているときに発生している可能性があります。

 listPushBack(sim->history, (void*)newRecord(p->pid, sim->currentTime, old, p->state));

#include解決策は、の完全な定義が完了していることを確認することです。つまり、上記のコードのどこかに#include"Process.h"Processを追加します。

于 2012-11-04T01:14:42.207 に答える
2

struct recordあなたのコメントは、history.cソースファイルで定義していることを示唆しています。struct record他のソースファイルでを使用している場合は、 history.hで定義する必要があります。そうしないと、別のファイルでポインタを使用しようとしたときに、この正確なエラーが発生しstruct recordます。

于 2012-11-04T01:41:59.977 に答える
1

あなたが抱えている問題は、simがポインタであるタイプが定義されていないことです。それは宣言されていますが(これはあなたがそれへのポインタを宣言する方法です)、定義されていません。言い換えれば、あなたはおそらく次のようなことをしたでしょう:

struct Simulation;

void myFunc() {
    struct Simulation* sim;
    sim->history;
}

sim->historylistPushBack呼び出しで行われたsimの履歴メンバーの逆参照はどこにありますか。

于 2012-11-04T01:13:10.800 に答える