【问题标题】:GLib Hash Table Lookup FailureGLib 哈希表查找失败
【发布时间】:2013-06-01 01:09:05
【问题描述】:

我正在尝试学习如何使用 glib 中的 GHashTable 容器,但在查找时发现了一些奇怪的行为。问题归结为以下几点:

#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。但是,如果我在调用 f2 之前从 main 调用 f1 并跳过从 f2 调用 f1,则代码将按预期工作并打印“HELLO”。

我想我在这里遗漏了一些非常基本的东西。如何在 glib 中正确进行哈希表插入和查找?

【问题讨论】:

  • 你能暂时用硬编码整数替换scanf 调用吗?
  • 我试过这样做,但结果是一样的。

标签: c glib


【解决方案1】:

我相信 GLib GHashTable 只接受作为指针的键。它不需要整数键。当您使用 g_int_hash 键函数创建哈希表时,您需要使用指向 gint 对象的指针从中获取,而不仅仅是普通整数。所以不是

g_hash_table_lookup(h, m)

试试

g_hash_table_lookup(h, g_new(gint, 1))

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

【讨论】:

  • 我刚刚对帖子进行了编辑,现在插入的是 `g_hash_table_insert(h, &k, val);` 并且查找是 g_hash_table_lookup(h, &amp;m);。但仍然得到相同的结果。
  • 变量 k 在 f1() 的末尾超出范围,因此它的地址不再有效。您必须使用持久分配的 int 的地址。您也可以考虑使用 g_direct_hash。
  • 那么,这是否意味着如果我想在 glib 哈希表中查找某些内容,我必须使用在将元素放在那里时用作键的相同精确对象?
  • 我想我现在明白了。显然 glib 不会在哈希表数据结构中保留 key 的副本,它只保留指向 key 的指针。
  • 正在做 g_hash_table_lookup(h, g_new(gint, 1));将泄漏一个 int 指针。您可以将哈希表设置为自动释放插入时使用的键和值,但对于查找,这只会泄漏。改为使用 GINT_TO_POINTER。
【解决方案2】:

您应该使用转换宏 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;
}

【讨论】:

  • 使用 GINT_TO_POINTER 作为键和 g_int_hash / g_int_equal 作为散列/查找函数会出现段错误。 g_int_hash 和 g_int_euqal 都将尝试取消引用指针,它并不是真正的指针(感谢 GINT_TO_POINTER)。你必须在调用g_hash_table_new时使用g_direct_hash / g_direct_equal。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多