Reputation: 873
As part of an assignment I'm doing for a university course, I need to write a CPU scheduling simulator in C (not C++). I'm hitting an issue when compiling with GCC where it's giving me several errors about "dereferencing pointer to incomplete type". All the errors are a result of the same code, which makes me think there's an issue with that code.
The offending code is:
//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));
This is related to keeping track of the history of the simulation for analysis later on. A record is defined as:
//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;
}
where ProcessState is defined as:
//Process.h
typedef enum process_state ProcessState;
enum process_state{
arrive = 0,
ready = 1,
run = 2,
wait = 3,
done = 4
};
I played around and got the same error with this:
Process p = (Process)listGetAt(sim->waitingQueue, i);
ProcessState old = p->state;
listPushBack(sim->history, (void*)newRecord(p->pid, sim->currentTime, old, p->state));
Thankfully, this isn't due for another week, so I've got time to play around, but I'm hoping someone can point me in the right direction before I waste too much time messing with things.
EDIT: Answering questions in order of appearance in comments,
//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;
}
Yes, Process is:
typedef process_Struct* Process
Simulation declaration:
//Simulation.c
struct simulation{
SimType type;
long currentTime;
unsigned int totalProcesses;
DoubleList arriveQueue;
DoubleList readyQueue;
DoubleList waitingQueue;
DoubleList doneQueue;
Process running;
DoubleList history;
};
The method that is throwing issues is runSimulation(Simulation sim) where:
typedef simulation* Simulation;
runSimulation is declared in Simulation.c
The exact error message is: source/Simulation.c:154:50: error: dereferencing pointer to incomplete type That's why this is proving so annoying, it doesn't give any more information then that, even with -verbose, -g, and some of the other debug flags.
I realize I shouldn't typdef pointers, but, stupidly enough, the professor made it a requirement of the assignment. To quote: "When possible, use typedef to define pointers to structs. This is so the TAs have an easier time reading your simulation code." I'm extremely annoyed by this because it's an awful idea and the TAs should be able to read code.
Upvotes: 3
Views: 688
Reputation: 65629
You typically see this error when you have only forward-declared something then go to use it. IE If you have:
// foo.h
struct Process;
// foo.c
#include "foo.h"
Process* foo;
std::cout << foo->i
You would get an error about derefencing a pointer of an incomplete type. That is likely what is happening when you are dereferencing p/sim on this line:
listPushBack(sim->history, (void*)newRecord(p->pid, sim->currentTime, old, p->state));
The solution is to make sure that you've #include
'd the full definition of Process
, ie add a #include "Process.h" somewhere in the code above.
Upvotes: 2
Reputation: 28362
The problem you are having is whatever type sim is a pointer to is not defined. It is declared (which is how you can declare a pointer to it), but not defined. In other words, you've probably done something like:
struct Simulation;
void myFunc() {
struct Simulation* sim;
sim->history;
}
Where sim->history
is the dereference of the history member of sim that's done in your listPushBack call.
Upvotes: 1
Reputation: 10027
Your comments suggest that you are defining struct record
in the history.c source file. If you are using a struct record
in any other source file, then you should define it in history.h, otherwise you will get this exact error when you try to use a pointer to struct record
in another file.
Upvotes: 2