Проблема с хеш-таблицей в glib. (Си)

Модератор: Модераторы разделов

Аватара пользователя
VarLog
Сообщения: 311
ОС: openSUSE 12.2

Проблема с хеш-таблицей в glib.

Сообщение VarLog »

Доброго времени суток.

Ломаю голову над тем, почему в хеш-таблице получаю либо SIGSEGV, либо "мусор" вместо данных по ключу. :)
Собственно, балуюсь с loudmouth, xmpp библиотекой на Си. Создаю хеш-таблицу, ключ - имя jabber конференции, значение - GList, со структурами whois_t.

Инициирую таблицу:

Код: Выделить всё

GHashTable *hash_whois;
hash_whois = g_hash_table_new_full(g_direct_hash, g_direct_equal, g_free, hash_whois_destroy);


При входе в конференцию в таблицу добавляется пустой GList:

Код: Выделить всё

GList *list_whois = g_new(GList, 1);
g_hash_table_insert(hash_whois, g_strdup(argv[1]), list_whois); //argv[1] - имя конференции


Затем из <presence>...</presence> сообщений берутся данные для whois струкуты:

Код: Выделить всё

struct _whois {
  gchar *room;
  gchar *nick;
  gchar *jid;
  gchar *affil;
  gchar *role;
};

typedef struct _whois whois_t;

Код: Выделить всё

whois_t *whois = g_new(whois_t, 1);
whois->room  = g_strdup(strip_jid(from));
whois->nick  = strip_res(from);
whois->jid   = jid ? g_strdup(jid) : NULL;
whois->affil = g_strdup(affil);
whois->role  = g_strdup(role);


Из хеш-таблицы достаётся GList соответствующей конференции и в этот лист добавляется whois_t структура:

Код: Выделить всё

GList *list_whois = g_hash_table_lookup(hash_whois, strip_jid(from));
list_whois = g_list_append(list_whois, whois);
g_hash_table_replace(hash_whois, g_strdup(strip_jid(from)), list_whois);


По моему всё верно, однако на деле что-то не то:

Код: Выделить всё

void see_whois(gpointer key, gpointer value, gpointer data) {
  printf("see_whois:\n");
  if(key && value) {
    printf("\tkey == %s\n", (char *)key);
    GList *list = value;
    for(; list; list=list->next) {
      whois_t *wh = list->data;
      if(wh->room)  printf("\t%s\n", wh->room);
      if(wh->nick)  printf("\t%s\n", wh->nick);
      if(wh->jid)   printf("\t%s\n", wh->jid);
      if(wh->affil) printf("\t%s\n", wh->affil);
      if(wh->role)  printf("\t%s\n", wh->role);
    }
  }
}

...
 g_hash_table_foreach(hash_whois, see_whois, NULL);

gdb:
Breakpoint 1, see_whois (key=0x8058870, value=0x8059d28, data=0x0) at commands.c:22
22 printf("see_whois:\n");
(gdb)
see_whois:
23 if(key && value) {
(gdb)
24 printf("\tkey == %s\n", (char *)key);
(gdb)
key == ololo@muc.varloghost.co.cc
25 GList *list = value;
(gdb)
26 for(; list; list=list->next) {
(gdb)
27 whois_t *wh = list->data;
(gdb)
28 if(wh->room) printf("\t%s\n", wh->room);
(gdb)
29 if(wh->nick) printf("\t%s\n", wh->nick);
(gdb)

Program received signal SIGSEGV, Segmentation fault.
0xb7dc17bb in vfprintf () from /lib/libc.so.6
(gdb)


Очевидно, что забыл где-то на что-то выделить память. Прошу помочь найти. :)
На самом деле всё очень просто...
Спасибо сказали: