1. 程式人生 > 其它 >關於malloc和free連結串列節點遇到的問題

關於malloc和free連結串列節點遇到的問題

連結串列初始化程式碼:

Node* list_init(void){
    Node *head = (Node *)malloc(sizeof(Node));
    Node *p1 = (Node *)malloc(sizeof(Node));
    Node *p2 = (Node *)malloc(sizeof(Node));
    Node *p3 = (Node *)malloc(sizeof(Node));
    Node *p4 = (Node *)malloc(sizeof(Node));
    Node *p5 = (Node *)malloc(sizeof(Node));
    head->val = -1;
    p1->val = 11;
    p2->val = 5;
    p3->val = 7;
    p4->val = 10;
    p5->val = 1;
    head->next = p1;
    p1->next = p2;
    p2->next = p3;
    p3->next = p4;
    p4->next = p5;
    p5->next = NULL;
    return head;
}

連結串列刪除程式碼:

void list_deinit(Node* head){
    while(head){
        Node* tmp = head;
        head = head->next;
        free(tmp);
        tmp = NULL;
    }
}

連結串列列印程式碼:

void list_print(Node* head){
    int first = 1;
    while (head)
    {
        if(first){
            first=0;
            printf("head->");
        }
        else{
            printf("(%d)->", head->val);
        }       
        head = head->next;
    }
    printf("NULL\n");
}

這時,在主函式中:

Node *head = list_init();
list_deinit(head);
list_print(head);

執行程式會報段錯誤,疑問點在於:list_print函式中已經加入了head=NULL的特殊情況判斷邏輯,但還是在deinit呼叫之後報錯

經過在init和deinit函式中列印連結串列各節點地址發現,deinit函式中傳入的只是head指標的一個副本;因此,在deinit函式中,head指標的副本以及連結串列其他節點已經全部釋放空間並指向了NULL

但是在主函式中,head指標指向的結構體被釋放了空間,但是並沒有賦值為NULL,因此,在deinit之後再呼叫list_print,實際上是傳入了一個野指標(此時的head),因此報了段錯誤。

修改後的程式程式碼原始檔如下:

void list_deinit(Node **head)
{
    while (*head)
    {
        Node** tmp = head;
        *head = (*head)->next;
        free(*tmp);
        *tmp = NULL;
    }
}//二級指標方法可以銷燬head本身,並不是傳入的副本

list_deinit(&head);//採用此方法呼叫