【问题标题】:hsearch_r overwrites hash tablehsearch_r 覆盖哈希表
【发布时间】:2015-11-05 02:50:00
【问题描述】:

我正在尝试查看是否可以在inotifywait 中添加一个新功能,该功能在观察阶段跟踪未收到任何事件的目录列表,并在退出之前打印该列表。 截至目前,inotifywait 能够在收到事件的目录上显示。我正在寻找的是未收到任何事件的目录列表。

为了实现这一点,我采取了以下方法。

  1. 当 inotifywait 放置监视时,使用 hsearch_r 生成一个包含所有目录的数组和一个哈希表,其中 key 为目录名,使用函数 hadd,value 作为刚刚为该目录创建的数组元素的索引。 See code here
  2. 当给定目录发生偶数时,我去step1中创建的哈希表,hfind取出这个目录名对应的值(即数组元素的索引),并设置元素在数组中的那个索引处为 NULL。见search for hash key
  3. 在退出 inotifywait 之前,我将打印数组中所有非 NULL 的元素。这实际上是没有从 inotifywait 收到任何 EVENT 的目录列表。

我看到的问题是,hadd 成功,并且对刚刚插入的元素的 hfind 的下一条语句有效。当 hsearch_r FIND 发生偶数时,上面的第 2 步失败。为了查看哈希表中有多少元素,我在执行hadd 之后,在hfind 中硬编码了一个目录名称。这仅在刚插入硬编码目录时通过。随后,下一次搜索失败,因为哈希表似乎已被下一个元素覆盖。

我希望有人能看出我哪里出错了。 我阅读了hsearch_r 的问题,并在那里进行了简短讨论后发布了一个新问题。

【问题讨论】:

  • “寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。 How to create a Minimal, Complete, and Verifiable example 不保证您提供的链接明天可以使用。这确保了代码可供未来的 SO 用户学习。

标签: c hashtable gnu


【解决方案1】:

我没有深入查看您的代码,但 hsearch 要求密钥的生命周期至少与 htables 的一样长,因为它只是按原样存储条目而没有深入指针的副本。

您使用临时指针来存储当前密钥;你经常aprintffree 这个指针。在第二次查找时,句柄不再有效。 (您可以在 Valgrind 中运行代码来查找此类内存访问错误。)

你可能会通过复制字符串而侥幸:

hadd(&tab, strdup(next_file), dir_count);

但这也不是一个合适的解决方案,因为当您销毁 htable 时,密钥的内存就会泄漏。

来自man hsearch

hdestroy()hdestroy_r() 函数不会释放哈希表条目的键和数据元素指向的缓冲区。

htable 不拥有数据。它只是为您必须自己管理的现有数据提供快速查找。 (它还有其他限制:必须事先知道最大条目数,并且不能删除项目。)

【讨论】:

  • @M Oehm:谢谢。您可能是对的,“因为它只是按原样存储条目而没有对指针进行深层复制。”凭借有限的知识,我设法理解了这种行为。 uthash 我认为是更好的哈希表实现。使用它,我可以让 inotifywait 做我想做的事。但是,我不得不再次像你建议的那样做一个strdup,即使在 uthash 中也是如此。我将尝试阅读更多内容以了解如何释放内存。
  • 是的,uthash 看起来不错。在销毁哈希表之前,您可以遍历这些项目 - 这是您无法使用 hsearch- 和 free 所有字符串做的事情。示例中的delete_all 函数表明了这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
相关资源
最近更新 更多