1

我想了解爲什麼我在下面的代碼的指定行(出現於:<<<SEGFAULT OCCURS HERE)中獲得段錯誤。我從this post獲得了很多靈感。試圖瞭解此分段錯誤

我認爲這是一個內存分配問題,但考慮到即使我將一個Event實例的指針傳遞給enqueue函數,它仍然存在段錯誤。考慮到C是按值傳遞的,即使當我將main中的事件地址(&event未顯示在此處的代碼中)傳遞給enqueue函數時,它應該指向存在於main中的事件實例的地址,對不對?所以我很難理解爲什麼發生分段錯誤。

請注意我正在尋找更多的原因爲什麼這是發生的,而不僅僅是一個問題的解決。畢竟,我正在努力提升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

'enqueue'函數被打破。您通過值傳遞'newEvent',這不會修改您傳遞的事件。 – pmr 2012-01-17 23:39:27

回答

3
Event **tail = NULL; 

tailNULL,和你提領它在你標記的代碼行。它需要做出指向一個Event*之前,你可以取消對它的引用:

要麼

Event *ev; 
Event **tail = &ev; 

或者

Event** tail = malloc(sizeof(Event*)); 

... 

free(tail); 

雖然,我覺得你的意思是剛纔的指針Event ,並按值傳遞其地址:

Event *tail = NULL, *head = NULL; 

... 

enqueue(event, &head, &tail); 

因此,0123在enqueue內修改了和tail

+1

問題標有'C';所以'新'是不合適的。 – Dave 2012-01-17 23:44:01

+0

@Dave抱歉,我總是忘記我是哪個標籤。對於這樣的愚蠢錯誤,請隨時編輯我的答案。 – 2012-01-18 00:25:20

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. 
    } 
} 
0

你的代碼包含至少兩個錯誤:

  1. 正如其他人你傳遞一個NULL指針尾巴和非關聯化將導致段錯誤
  2. 您在newEvent按值傳遞指出。這意味着結構的副本將被製作並放入堆棧。在函數內部,你可以執行*head = &newEvent,它接收堆棧中的對象地址並將其放入隊列中。從入隊函數返回後,堆棧將被清理,並指向垃圾。您需要將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堆上通過返回從parseLineIntoEventEvent *(使用malloc到異體爲它記憶內存)