我试图理解为什么我在下面的代码指示行中得到段错误(注意:<<<SEGFAULT OCCURS HERE
)。我用this post的灵感来写这篇文章。
我认为这是一个内存分配问题,但考虑到即使我将一个Event实例的指针传递给enqueue函数,它仍然是段错误。考虑到C是按值传递的,即使我将main中的事件地址(我在此处发布的代码中未显示&event
)传递给enqueue函数,它也应该指向存在于的事件实例的地址。主,对吗?所以我很难理解为什么会发生分段错误。
请注意我正在寻找更多原因,而不仅仅是修复问题。毕竟我正在研究C上的刷新。 :)
相关代码:
typedef struct Event_ Event;
struct Event_ {
char action[4];
long timestamp;
char* path;
char hash[9];
Event *nextEvent; // pointer to next Event instance in Queue
};
// Enqueues newEvent into queue. Returns 1 on success, 0 otherwise.
int enqueue(Event newEvent, Event **head, Event **tail) {
if (head != NULL) {
// make the old head point to the newly inserted Event,
// and the new Event to point to NULL (nothing comes before head):
(*head) -> nextEvent = &newEvent;
newEvent.nextEvent = NULL;
} else {
// first element being added to queue.
*tail = &newEvent; //<<<SEGFAULT OCCURS HERE
}
// designate the new Event as the new head:
*head = &newEvent;
return 1;
}
// Parse line and return an Event struct.
Event parseLineIntoEvent(char* line) {
Event event = {0};
char* lineSegment;
int i = 0;
lineSegment = strtok(line, " ");
while (lineSegment != NULL) {
if (i > 3) {
printf("WARNING: input format error!\n");
break;
}
if (i == 0)
strncpy(event.action, lineSegment, sizeof(event.action)-1);
else if(i == 1)
event.timestamp = atoi(lineSegment);
else if(i == 2) {
event.path = malloc(sizeof(char) * (strlen(lineSegment) + 1));
strcpy(event.path, lineSegment);
} else if(i == 3)
strncpy(event.hash, lineSegment, sizeof(event.hash)-1);
lineSegment = strtok(NULL, " ");
i++;
} // while
return event;
} // parseLineIntoEvent()
int main (int argc, const char * argv[]) {
//...
Event **head = NULL;
Event **tail = NULL;
for (; numLines > 0; numLines--) {
char *line = getLineFromStdin(); //malloced char array being returned
printf("%s\n",line);
Event event = parseLineIntoEvent(line);
if(!enqueue(event, head, tail))
printf("An error occurred when attempting to enqueue an Event.\n");
event = dequeue(head, tail);
//...
free(event.path);
free(line);
}
return 0;
}
提前致谢!
答案 0 :(得分:3)
Event **tail = NULL;
tail
是NULL
,您在标记的行上取消引用它。在取消引用它之前,需要指向Event*
:
无论
Event *ev;
Event **tail = &ev;
或者
Event** tail = malloc(sizeof(Event*));
...
free(tail);
尽管如此,我认为你的意思是只指向一个Event
,并按值传递其地址:
Event *tail = NULL, *head = NULL;
...
enqueue(event, &head, &tail);
以便在head
内修改tail
和enqueue
。
答案 1 :(得分:0)
您正在取消引用空指针。
int main (int argc, const char * argv[]) {
//...
Event **head = NULL;
Event **tail = NULL;
for (; numLines > 0; numLines--) {
//...
if(!enqueue(event, head, tail)) // head and tail are NULL here
//...
}
}
int enqueue(Event newEvent, Event **head, Event **tail) {
if (head != NULL) { // head is NULL, else path will be executed
//...
} else {
// first element being added to queue.
*tail = &newEvent; //<<<SEGFAULT OCCURS HERE because tail is null.
}
}
答案 2 :(得分:0)
您的代码至少包含两个错误:
newEvent
。这意味着将生成结构的副本并将其放在堆栈中。在函数内部执行*head = &newEvent
,它获取堆栈中对象的地址并将其放入队列中。从enqueue函数返回后,堆栈将被清理并指向垃圾。您需要将eneueue
更改为int enqueue(Event *newEvent, Event **head, Event **tail)
并传递指向该事件的指针。我不确定为什么你使用指针指针,你的队列似乎在语义上被破坏(头部通常是开始,enqueue
通常在末尾附加东西)
int enqueue(Event *event, Event **head, Event **tail)
{
if (*head != NULL)
{
// we do have a head: point next to current head
event->nextEvent = *head;
}
else
{
// no head so we also should have no tail
*tail = event;
event->nextEvent = NULL;
}
// newly enqueued event is now head
*head = event;
return 1;
}
使用它:
Event *head = NULL;
Event *tail = NULL;
...
Event newEvent = parseLineIntoEvent(char* line);
enqueue(&newEvent, &head, &tail);
虽然您应该考虑通过从newEvent
返回Event *
来将parseLineIntoEvent
放在堆上(使用malloc
为其分配内存)