2012-10-04 34 views
1

我寫了一段代碼來實現哈希函數。在將第9個元素「a12a」添加到列表中時,問題出現了,gdb報告如下,並且似乎在malloc應用內存過程中發生了問題。但是在添加第9個元素之前,我添加第6個元素「ad」時成功應用了malloc的一次內存,爲什麼第二次應用內存失敗?爲什麼在malloc中Segmentation出現錯誤?

Breakpoint 1, insert (p=0x3d2d10, value=0x4030e8 "a12a") at hashop.c:39 
39    id = hash(value); 
(gdb) n 
40    *current = p + id; 
(gdb) 
41    if((*current)->value == NULL) { 
(gdb) 
44      if((lookup(p+id, value)) == NULL) { 
(gdb) 
45        new = (nList *)malloc(sizeof(nList)); 
(gdb) 

Program received signal SIGSEGV, Segmentation fault. 
0x7c938996 in ntdll!RtlDuplicateUnicodeString() 
    from C:\WINDOWS\system32\ntdll.dll 
(gdb) 

而且我的代碼是:

void insert(nList *p, char *value) 
{ 
    nList *new, **current; 
    int id; 

    id = hash(value); 
    *current = p + id; 
    if((*current)->value == NULL) { 
     (*current)->value = value; 
    } else { 
     if((lookup(p+id, value)) == NULL) { 
      new = (nList *)malloc(sizeof(nList)); 
      new->value = value; 
      new->next = NULL;  
      while((*current)->next != NULL) { 
       (*current) =(*current)->next; 
      } 
      (*current)->next = new; 
     } 
    } 
} 

static char *str2[] = {"ac", "ba", "abv", "bc", "bx", "ad", "xx", "aaa", "a12a", "b123"}; 

,每個元素的哈希ID是如下:

ac, HashId=6 
ba, HashId=5 
abv, HashId=3 
bc, HashId=7 
bx, HashId=8 
ad, HashId=7 
xx, HashId=0 
aaa, HashId=1 
a12a, HashId=3 
b123, HashId=8 

從上面的列表中,這是肯定的 「BC」 和「ad」具有相同的散列ID,因此在我的insert()函數中,我將應用一塊內存來存儲「ad」。 「abv」和「a12a」也是一樣,我也應用了一塊內存,但是這次失敗了。爲什麼?任何人都可以弄清楚?不勝感激!

+0

您應該瞭解更多關於'gdb',特別是'p','display','break','bt','watch'命令。而你並沒有告訴我們足夠的真正幫助。 –

+1

當你第一次初始化列表時,你是否將所有'next'設置爲NULL?也許'ad'的指針會很幸運。 – LSerni

回答

4

你破壞內存,此行:

*current = p + id; 

通行證-Wall到GCC打開所有的警告,你會看到:

buggy-hash.c: In function ‘insert’: 
buggy-hash.c:19:14: warning: ‘current’ is used uninitialized in this function [-Wuninitialized] 

提示:使用gcc -Wall和運行程序在Linux下的內存調試器如Valgrind下可以更容易找到這些內存問題lot

我猜你正在使用CodeBlocks或Windows下的其他IDE學習C編程?在Visual Studio中以調試模式構建程序也會遇到這些問題。

+0

感謝scottt指出-Wall參數,它很有用。 – user1528396

0

問題是我用p + id作爲查找函數的輸入,但忘記了p已經被* current改變了。所以正確的代碼是:

void insert(nList *p, char *value) 
{ 
    nList *new, **current = &p; 
    int id; 
    id = hash(value); 
    *current += id; 

    if((*current)->value == NULL) { 
     (*current)->value = value; 
    } else { 
     if((lookup(*current, value)) == NULL) { 
      new = (nList *)malloc(sizeof(nList)); 

      if(new == NULL) 
       printf("\nCannot get memory"); 
      else { 
       new->value = value; 
       new->next = NULL;  

       while((*current)->next != NULL) { 
        (*current) =(*current)->next; 
       } 

       (*current)->next = new; 
      } 
     } 
    } 
} 
相關問題