3

作为我为大学课程做的作业的一部分,我需要用 C(不是 C++)编写一个 CPU 调度模拟器。我在使用 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));

谢天谢地,这不会再过一周了,所以我有时间玩,但我希望有人能在我浪费太多时间搞砸事情之前指出正确的方向。

编辑:按出现在评论中的顺序回答问题,

//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: error: dereference pointer to incomplete type 这就是为什么这很烦人,它没有提供更多信息,即使使用 -verbose, -g,和其他一些调试标志。

我意识到我不应该输入 typdef 指针,但是,愚蠢的是,教授把它作为作业的要求。引用:“如果可能,请使用 typedef 定义指向结构的指针。这样 TA 可以更轻松地阅读您的模拟代码。” 我对此感到非常恼火,因为这是一个糟糕的主意,助教应该能够阅读代码。

4

3 回答 3

2

您的评论表明您struct recordhistory.c源文件中进行定义。如果您struct record在任何其他源文件中使用 a ,那么您应该在history.h中定义它,否则当您尝试struct record在另一个文件中使用指向时,您将得到这个确切的错误。

于 2012-11-04T01:41:59.977 回答
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完整定义了Process,即在上面的代码中的某处添加一个#include "Process.h" 。

于 2012-11-04T01:14:42.207 回答
1

您遇到的问题是未定义任何类型的 sim 指针。它已声明(这是您可以声明指向它的指针的方式),但未定义。换句话说,你可能做过类似的事情:

struct Simulation;

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

sim->history您的 listPushBack 调用中完成的 sim 历史成员的取消引用在哪里。

于 2012-11-04T01:13:10.800 回答