2013-04-29 54 views
0

貝婁是相關代碼:無法將第二個元素插入到鏈表|函數指針被損壞

typedef struct Node_t { 
    ListElement data; 
    struct Node_t* next; 
} Node; 

struct List_t { 
    Node* head; 
    Node* tail; 
    Node* current; 
    int size; 
    CopyListElement copyF; 
    FreeListElement freeF; 
}; 

static ListResult initializeNode(List list, ListElement element, Node* newNode){ 
    printf("\nEntered initializeNode\n"); 
    if ((list == NULL) || (element == NULL)) return LIST_NULL_ARGUMENT; 
    newNode = malloc(sizeof(Node)); 
    if (newNode == NULL) return LIST_OUT_OF_MEMORY; 
    printf("\nWithin initializeNode, before copyF\n"); 
    ListElement newElement = list->copyF(element); 
    printf("\nWithin initializeNode, after copyF\n"); 
    if (newElement == NULL) return LIST_OUT_OF_MEMORY; 
    newNode->data = newElement; 
    printf("\nLast line within initializeNode\n"); 
    return LIST_SUCCESS; 
} 

List listCreate(CopyListElement copyElement, FreeListElement freeElement){ 

    //Check if there is a NULL argument. 
    if ((copyElement == NULL) || (freeElement == NULL)) return NULL; 

    //Check wether there is enough memory. 
    List newList = malloc(sizeof(List)); 
    if (newList == NULL) return NULL; 
    //Initialize an empty List. 
    newList->head = NULL; 
    newList->tail = NULL; 
    newList->size = 0; 
    newList->current = NULL; 
    newList->copyF = copyElement; 
    newList->freeF = freeElement; 

    return newList; 
} 

ListResult listInsertFirst(List list, ListElement element){ 
    printf("\nEntered listInsertFirst\n"); 
    Node* newNode; 
    ListResult result = initializeNode(list, element, newNode); 
    printf("\n Node was initialized\n"); 
    if (result != LIST_SUCCESS) { 
     return result; 
    } 

    printf("\nEntering logistic works within listInsertFirst\n"); 
    //Finish logistic work within the Node. 
    newNode->next = list->head; 
    list->head = newNode; 
    list->size++; 
    printf("\nElement was inserted successfully\n"); 

printf("\nCheck list->CopyF within listInsertFirst\n"); 
list->copyF(element); 
printf("\nCheck list->CopyF within listInsertFirst: PASSED\n"); 

    return LIST_SUCCESS; 
} 

在主要功能離子我想:

List list = listCreate(&copyInt, &freeInt); 

ListResult result; 
int el=2; 
//ListElement e1; 
//ListElement e2; 

result = listInsertFirst(list,&el); 
printf("\nresult = %d\n", result); 

result = listInsertFirst(list,&el); 
printf("\nresult = %d\n", result); 

編譯並運行後我得到:

進入listInsertFirst

copyF

進入initializeNode

在initializeNode,在init中ializeNode,copyF

內initializeNode最後一行

節點被初始化

進入內listInsertFirst

後勤工作後

元素被成功

檢查插入列表 - > CopyF listInsertFirst分段故障之內: 11

由於某種原因,指向[函數] list-> copyF的指針被破壞[我認爲]。

+0

你使用了哪些編譯器標誌?我會嘗試的第一件事是添加-Wall -Wextra。另外,你有沒有試過Valgrind? – 2013-04-29 06:58:13

回答

1

我假設這是基於標籤的C代碼,而不是C++。鑑於你有混合的數據定義和實際的代碼語句,我不希望在C中工作,我不是100%確定它是真實的C,在這種情況下,我可能是錯誤的下面的錯誤。

首先,initializeNode()的接口不會做你可能打算的。你可能想要:

static ListResult initializeNode(List list, ListElement element, Node** newNodep) 
{ 
    Node *newNode = malloc(sizeof(Node)); 
    if (newNode == NULL) return LIST_OUT_OF_MEMORY; 
    ListElement newElement = list->copyF(element); 
    if (newElement == NULL) return LIST_OUT_OF_MEMORY; 
    newNode->data = newElement; 
    *newNodep = newNode; 
    return LIST_SUCCESS; 
} 

這樣你創建的節點會被傳回。

我不知道CopyInt()是做什麼的,但是如果它真的發揮了總線錯誤的功能,initializeNode()的錯誤不能成爲你的問題。但是,在報告崩潰之前,您可能沒有看到所有printfs的輸出。

如果CopyInt()做我所期望的,但它確實是這樣的:

ListElement CopyInt(int *val) 
{ 
    ListElement *e = malloc(sizeof(ListElement)); 
    if (e) 
     e->val = *val; 
    return e; 
} 

,你會得到一個在這裏第二次總線錯誤的唯一方法是,如果你搞砸了數據結構由庫函數malloc()維護。不幸的是,對於這個理論,我沒有看到比這裏的內存泄漏更糟的事情。

+0

感謝您的回答,我需要一些時間來分析它。 順便說一下,這是C99。 – 2013-04-29 02:41:33

+0

initializeNode獲取一個指向Node的指針,所以我不認爲你的initializeNode的修正是「好的」。 – 2013-04-29 02:47:13

+0

縮小了這個問題,編輯了原始問題。 – 2013-04-29 02:54:31

0

我的猜測,實際上導致崩潰的bug是這一行:

newNode->next = list->head;

像@Arlie斯蒂芬斯說 - 作爲指針由值和通過了initializeNode代碼不會做任何事情實際的指針仍然指向垃圾。所以當你做newNode->next = list->head;時,你基本上是在寫一個未知地址,很可能會出現分段錯誤。 爲什麼只發生在第二個電話?不知道,這是未定義的行爲。

瘋狂的想法 - 有可能是newNode-> next被初始化爲copyF的地址,並試圖寫入它會導致你損壞copyF ...嘗試打印newNode-> next的地址和copyF的地址。