有關錯誤的項目順序
您的slist_impl_insertl()
邏輯是錯誤的。
讓我們來看看你的代碼:
stringlist_t* slist_impl_insertl(stringlist_t* list, const char* str, unsigned int len)
{
stringlist_t* newnode;
if(list == NULL) // if the list is empty
{
newnode = slist_createl(str, len); // create a new item
list = newnode; // insert the new item at the start of the list
return list;
}
else // if the list is not empty
{
if(list->next == NULL) // if it contains only one item
{
list = slist_insertb(list, str, len); // insert a new item at the front of the list
return list;
}
else // if it contains more than one item
{
newnode = slist_createl(str, len); // create a new node
newnode->next = (struct stringlist_t*)list->next; // insert the new node just after the first item !?!.
list->next = (struct stringlist_t*)newnode;
return list;
}
}
return list; /* not reached */
}
所以,你插入過程並不總是插在同一個地方的新節點。它有時插入在開始,有時插入在第二個地方。這解釋了爲什麼這些項目按錯誤順序排序。
一個簡單的解決方法是總是在列表的開始處插入新節點,然後這些項目將以相反的順序屈服。或者你可以直到你到達終點(list->next == NULL
)遍歷列表,而這最後一個項目之後插入新項目:
stringlist_t* slist_impl_insertl(stringlist_t* list, const char* str, unsigned int len)
{
stringlist_t *iter;
if(list == NULL)
{
list = slist_createl(str, len);
}
else
{
// find the last ist item
iter = list;
while(iter->next!=NULL)
iter = iter->next;
// insert the new item at the end of the list
iter->next = slist_createl(str,len);
}
return list;
}
有關使用宏
如果列表爲空(list == NULL
) ,您的插入過程將修改列表以使其成爲第一項。宏處理重新分配修改後的列表。如果您不想使用宏,那麼您必須將列表參數作爲指針傳遞,以便您可以在插入過程中直接修改它。
(誰擺在首位寫的代碼的傢伙說得那麼他可以在列表中的任意位置插入一個項目,而無需編寫特定的程序來執行)
這裏是一個候選實施的slist_insert()
不使用宏:
void slist_insert(stringlist_t** list, const char* str)
{
*list = slist_impl_insertl(*list, str);
}
使用這個實現,你必須改變你的列表中插入項目的方式:
slist_insert(&list, "red"); // note the use of '&'
關於內存泄漏
銷燬過程釋放存儲在每個項目中的字符串,沒關係。但每個項目也是動態分配的,因此他們也需要被釋放!您必須臨時存儲列表指針,前進到下一個項目,然後釋放存儲的指針,直到到達列表的末尾。
void slist_destroy(stringlist_t* list)
{
stringlist_t *temp;
while(list != NULL)
{
// free the data contained in the current list item
free(list->data);
// save the pointer to the next item
temp = slist_next(list);
// free the current item
free(list);
// continue with the next item
list = temp;
}
}
這是太多的代碼。嘗試進一步調試它,但首先運行你的代碼只添加_one_元素,然後只有兩個,然後只有三個。確保您的刪除在上述所有三種情況下均有效。你應該能夠用筆和紙跟蹤你的分配。 – Mat
@Mat噢,我* *已經*用valgrind(分別用'--leak-check = full')和gdb調試代碼,無濟於事。即使在循環內部的「slist_destroy」中有一個額外的'free(list)'(在分配給下一個列表之前)也不會關閉內存泄漏。因此,這個問題。 – hiobs