hsearch_r 覆盖散列 table

hsearch_r overwrites hash table

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

为了实现这一目标,我采用了以下方法。

  1. 当 inotifywait 放置手表时,生成所有目录的数组,以及使用 hsearch_r 的散列 table,键作为目录名称,使用函数 hadd,以及值作为刚刚为此目录创建的数组元素的索引。See code here
  2. 当一个给定的目录出现偶数时,然后,我去step1中创建的散列table,hfind取出这个目录名对应的值(这是目录的索引)数组元素),并将数组中该索引处的元素设置为 NULL。参见 search for hash key
  3. 在退出 inotifywait 之前,我将打印数组中所有非 NULL 的元素。这实际上是未从 inotifywait 接收到任何 EVENT 的目录列表。

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

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

我没有深入查看您的代码,但 hsearch 要求密钥的生命周期至少与 htables 的生命周期一样长,因为它只是将条目存储为它没有对指针进行深度复制。

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

您可能可以复制字符串:

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

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

来自man hsearch

The hdestroy() and hdestroy_r() functions do not free the buffers pointed to by the key and data elements of the hash table entries.

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