2011-08-10 70 views
0

我寫了下面的玩具程序來測試「g_hash_table_lookup()」遞歸內:g_hash_table_lookup在遞歸


#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <glib.h> 
#include <string.h> 

void f_recursive(GHashTable *htable, int level){ 
    char key[] = "test_key"; 
    char value[] = "test_value"; 
    char *returned_value; 

    if(level > 0){ 
     f_recursive(htable, level - 1); 
    } 
    else if(level==0){ 
     g_hash_table_insert(htable,&key[0],&value[0]); 
    } 

    returned_value = g_hash_table_lookup(htable,&key[0]); 
    printf("Level=%d, Returned Value=%s\n",level, returned_value); 
} 

int main(int argc, char * argv[]){ 
    int i=3; 
    GHashTable *Hash_Table; 

    Hash_Table = g_hash_table_new(g_str_hash,g_str_equal); 
    f_recursive(Hash_Table, i); 
} 

這段代碼的目的很簡單,就是調用遞歸函數在遞歸的每個級別,在哈希表中查找僅在遞歸的最低級別插入的密鑰的值。我的期望是,在遞歸的每一層,我可以恢復控制在最低水平插入值,所以這個方案的預期輸出應該是:

Level=0, Returned Value=test_value 
Level=1, Returned Value=test_value 
Level=2, Returned Value=test_value 
Level=3, Returned Value=test_value 

然而,這是不會發生什麼變化。相反,我得到如下:

Level=0, Returned Value=test_value 
Level=1, Returned Value=([��`� 
Level=2, Returned Value=(null) 
Level=3, Returned Value=(null) 

我將不勝感激,如果有人可以解釋我爲什麼我能夠在只在我做插入的遞歸水平,檢索在哈希表中插入的值。

謝謝!

丹尼爾

回答

1

fine manual

注意,當插入到GHashTable鍵和值都不被複制,因此它們必須存在GHashTable的壽命。

這意味着,這樣的:

g_hash_table_insert(htable,&key[0],&value[0]); 

不復制keyvalue,哈希表只是存儲的指針。然而,keyvalue被分配在棧上:

char key[] = "test_key"; 
char value[] = "test_value"; 

所以你&key[0]&value[0]指針僅適用於功能的持續時間。一旦你退出了你的遞歸,你就有了一個散列表,裏面充滿了無效的指針,這給你一堆垃圾和未定義的行爲。

您應該使用g_hash_table_new_full,同時釋放鍵和值的函數,然後在撥打g_hash_table_insert時複製您的密鑰和值;您可以使用g_strdup複製密鑰和值並將g_free作爲key_destroy_funcvalue_destroy_func參數複製到g_hash_table_new_full

+0

非常感謝,我應該考慮一下。據我的理解,「g_hash_table_new_full()」是否保存鍵和值的副本,而不是指向它們的指針?還是由「g_strdup()」創建的副本在被「g_free」明確釋放之前以某種方式保持「活着」? –

+0

@Dani:不,哈希表只複製指向的指針而不是它們指向的指針。 'g_strdup'幾乎就是'malloc'和'strcpy',這就是爲什麼你需要使用哈希表構造函數的長形式(帶有兩個釋放函數的版本),或者確保你手動清理內存。 –