2012-02-24 112 views
1

我寫下了下面的程序,該程序使用quicksort算法來排序使用鏈接列表將多少個整數放入命令行的方式。我不僅得到關於混合聲明的ISO C90錯誤,而且我的代碼中存在內存泄漏,我不知道如何解決它。任何幫助,將不勝感激!帶鏈接列表的快速排序

#include <stdio.h> 
#include "linked_list.h" 
#include <stdlib.h> 
#include "memcheck.h" 
#include <string.h> 
#include <assert.h> 

node *quicksort(node *list); 
int ListLength (node *list); 

int main(int argc, char *argv[]) { 
    if (argc == 1) { 
    fprintf(stderr, "usage: %s [-q] number1 number2 ... \ 
    (must enter at least one argument)\n", argv[0]); 
    exit(1); 
    } 
    node *list; 
    node *sorted_list; 
    int i; 
    int intArg = 0; /* number of integer arguments */ 
    int print = 1; 
    /* if -q is found anywhere then we are going 
    * to change the behavior of the program so that 
    * it still sorts but does not print the result */ 
    for (i = 1 ; i < argc; i++) { 
     if (strcmp(argv[i], "-q") == 0) { 
      print = 0; 
     } 
     else { 
      list = create_node(atoi(argv[i]), list); /* memory allocation in the   create_node function */ 
      intArg++; } 
    } 

    if (intArg == 0) { 
     fprintf(stderr, "usage: %s [-q] number1 number2 ...\ 
     (at least one of the input arguments must be an integer)\n", argv[0]); 
     exit(1); } 
    sorted_list = quicksort(list); 
    free_list(list); 
    list = sorted_list; 
    if (print == 1) { 
     print_list(list); } 
    print_memory_leaks(); 
    return 0; } 

/* This function sorts a linked list using the quicksort 
* algorithm */ 
node *quicksort(node *list) { 
node *less=NULL, *more=NULL, *next, *temp=NULL, *end; 
node *pivot = list; 
if (ListLength(list) <= 1) { 
    node *listCopy; 
    listCopy = copy_list(list); 
    return listCopy; } 
else { 
    next = list->next; 
    list = next; 
    /* split into two */ 
    temp = list; 
    while(temp != NULL) { 
     next = temp->next; 
     if (temp->data < pivot->data) { 
      temp->next = less; 
      less = temp; 
    } 
     else { 
      temp->next = more; 
      more = temp; 
    } 
     temp = next; 
    } 
    less = quicksort(less); 
    more = quicksort(more); } 
    /* appending the results */ 
if (less != NULL) { 
    end = less; 
    while (end->next != NULL) { 
     end = end->next; 
    } 
pivot->next = more; 
end->next = pivot; 
return less; } 
else { 
    pivot->next = more; 
return pivot; } } 
int ListLength (node *list) { 
    node *temp = list; 
    int i=0; 
    while(temp!=NULL) { 
     i++; 
     temp=temp->next; } 
return i; } 
+0

什麼是編譯器錯誤信息?你怎麼知道有內存泄漏? – 2012-02-24 01:07:44

+0

它通過分配內存開始,然後打印出我以正確順序輸入的一些數字,但是停止並打印內存泄漏線:78和更高版本在第20行一堆。 – 2012-02-24 01:13:16

+0

混合聲明錯誤可能是在聲明變量之前檢查argc。如果我在gcc中使用-pedantic標誌進行編譯,我會得到這個結果。 – foo 2012-02-24 01:18:51

回答

1

main,你自由一個節點,列表的原廠頭:

sorted_list = quicksort(list); 
free_list(list); 

但你永遠不會釋放任何其他節點,儘管你複製的節點。因此,從第一個節點保存的所有原始列表節點都將浮動在不可訪問的內存中。要麼複製free,要麼複製freemain,要麼完全不復制(並釋放main中的所有節點,但只在不再需要它們之後)。

+0

你是不正確的。 main中唯一的其他節點是sorted_list,它在釋放時不能解決問題。 – 2012-02-24 03:14:58

+0

我期望'list = create_node(atoi(argv [i]),list);'分配節點,尤其是給出該行的註釋。你從來沒有直接引用除主體之外的任何一個(可能在排序後兩個)。然後在'quicksort'中,當達到長度1時,'copy_list'節點,忘記原始節點。因此,您可以從複製的節點中組裝已排序的列表,這些節點的原始文件未被釋放(通常很快就無法訪問)。另外,'list'指向原始頭,這是第一個關鍵點。樞軸不被複制,因此它是排序列表的一部分。 ... – 2012-02-24 03:31:45

+0

當你釋放它時,你撕開排序後的列表,它的前任現在有一個懸掛指針,並且後面的節點不再可達(但如果它從未被覆蓋,則可能不會注意到)。 – 2012-02-24 03:31:51

1

好了,你有沒有張貼free_list()create_node()這些都是潛在的內存泄漏總理候選人的代碼,但我相信你的quicksort()代碼有內存泄漏的位置:

less = quicksort(less); 
    more = quicksort(more); } 

如果任一列表中只有一個元素,那麼這個代碼:

if (ListLength(list) <= 1) { 
    node *listCopy; 
    listCopy = copy_list(list); 
    return listCopy; } 

返回一個元素的副本。通過在這裏設置lessmore指針,您可能會丟失單個節點。

考慮名單:2 1 3

的代碼將增加1less列表,3more列表。然後它會在這兩個單元素列表上執行quicksort(),返回列表的副本,並丟失指向原始lessmore列表的指針,導致兩個節點的內存泄漏。

巧合的是,這將是更好,以取代上述與if語句的檢查:

if (list == NULL || list->next == NULL) { 

這避免了遍歷一個潛在的一長串只是爲了檢查是否只包含0或1個元素。