2013-06-01 6 views
1

Я пытаюсь узнать, как использовать контейнер GHashTable из glib, и я вижу странное поведение в поиске. Проблема сводится к следующему:Ошибка поиска в таблице Hash Hash

#include <glib.h> 
#include <stdio.h> 

GHashTable *h; 
char val[] = {'H', 'E', 'L', 'L', 'O',0}; 

void f1() 
{ 
    int k; 
    scanf("%d", &k); 
     g_hash_table_insert(h, &k, val); 
} 

void f2() 
{ 
    int m; 
    f1(); 
    scanf("%d", &m); 
    gpointer *p = g_hash_table_lookup(h, &m); 
    printf("%s\n", (const char*)p); 
} 

int main() 
{ 
    h = g_hash_table_new(g_int_hash, g_int_equal); 
    f2(); 
    return 0; 
} 

В функции f2, результатом g_hash_table_lookup является 0x00. Однако, если я позвоню f1 из основного номера до звонка f2 и пропустил вызов f1 от f2, код работает должным образом и печатает «HELLO».

Я думаю, что мне не хватает чего-то очень элементарного здесь. Как сделать хэш-таблицы вставки и поиск правильно в glib?

+0

Можете ли вы временно заменить вызовы 'scanf' целым целым числом? – Anthony

+0

Я пытался это сделать, но результат тот же. –

ответ

1

Я считаю, что GLib GHashTable принимает только ключи, которые являются указателями. Он не принимает целых ключей. Когда вы создаете хэш-таблицу с помощью ключевой функции g_int_hash, вам нужно извлечь ее с помощью указателей на объекты gint, а не только простые int. Таким образом, вместо

попробовать

g_hash_table_lookup(h, g_new(gint, 1)) 

См http://blog.sensecodons.com/2012/01/glib-ghashtable-and-gdirecthash.html

+0

Я только что редактировал сообщение, теперь вставляем 'g_hash_table_insert (h, & k, val);' и lookup является 'g_hash_table_lookup (h, &m);'. Все равно получается тот же результат. –

+0

Переменная k выходит за рамки в конце f1(), поэтому адрес больше недействителен. Вам нужно будет использовать адрес постоянно выделенного int. Вы также можете рассмотреть возможность использования g_direct_hash. –

+0

Итак, значит ли это, что если я хочу что-то посмотреть в glib hashtable Мне нужно использовать тот же точный объект, который использовался в качестве ключа при размещении элемента там? –

1

Вы должны использовать GINT_TO_POINTER Макроконверсия, смотрите здесь: https://developer.gnome.org/glib/2.34/glib-Type-Conversion-Macros.html

так:

#include <glib.h> 
#include <stdio.h> 

GHashTable *h; 
char val[] = {'H', 'E', 'L', 'L', 'O',0}; 

void f1() 
{ 
    int k; 
    scanf("%d", &k); 
    g_hash_table_insert(h, GINT_TO_POINTER(k), val); 
} 

void f2() 
{ 
    int m; 
    f1(); 
    scanf("%d", &m); 
    gpointer *p = g_hash_table_lookup(h, GINT_TO_POINTER(m)); 
    printf("%s\n", (const char*)p); 
} 

int main() 
{ 
    h = g_hash_table_new(g_int_hash, g_int_equal); 
    f2(); 
    return 0; 
} 
+0

Использование 'GINT_TO_POINTER' для ключа и' g_int_hash'/'g_int_equal' для функций хэша/поиска будет segfault. И 'g_int_hash', и' g_int_euqal' будут пытаться разделять указатель, и это не является указателем (благодаря 'GINT_TO_POINTER'). Вы должны использовать 'g_direct_hash' /' g_direct_equal' в вызове 'g_hash_table_new'. – flihp