hsearch_r перезаписывает хеш-таблицу

Я пытаюсь посмотреть, смогу ли я добавить новую функцию в inotifywait, которая во время фаза наблюдения отслеживает список каталогов, в которых не было никаких событий, и перед завершением распечатывает этот список. На данный момент inotifywait может отображать каталоги, получившие событие. Я ищу список каталогов, которые не получили никаких событий.

Чтобы добиться этого, я использую следующий подход.

  1. Пока inotifywait размещает часы, создайте массив всех каталогов и хеш-таблицу, используя hsearch_r с ключом в качестве имени каталога, используя функцию hadd и значение в качестве индекса элемента массива, только что созданного для этого каталога.см. код здесь
  2. Когда даже происходит в данном каталоге, я перехожу к хэш-таблице, созданной на шаге 1, hfind из значения, соответствующего этому имени каталога (которое является индексом элемента массива), и устанавливаю элемент по этому индексу в массив в NULL. См. поиск хеш-ключа
  3. Прежде чем выйти из inotifywait, я распечатаю все элементы массива, которые не равны NULL. По сути, это список каталогов, которые не получили никакого СОБЫТИЯ от inotifywait.

Проблема, которую я вижу, заключается в том, что hadd выполняется успешно, и следующий оператор hfind для только что вставленного элемента работает. Когда hsearch_r НАЙТИ, когда происходит даже, шаг 2 выше не выполняется. Чтобы увидеть, сколько элементов содержится в хеш-таблице, я жестко закодировал имя каталога в hfind после того, как сделал hadd. Это проходит только тогда, когда жестко закодированный каталог только что вставлен. Впоследствии следующий поиск завершается ошибкой, потому что хэш-таблица, похоже, была перезаписана следующим элементом.

Я надеюсь, что кто-нибудь увидит, где я ошибся. Я прочитал вопрос hsearch_r и опубликовал новый после краткого обсуждения.


person venkrao    schedule 04.11.2015    source источник
comment
Вопросы, требующие помощи в отладке (почему этот код не работает?), должны включать желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для их воспроизведения, в самом вопросе. Как создать минимальный, полный и проверяемый пример Нет гарантии, что предоставленная вами ссылка будет работать завтра. Это гарантирует, что код будет доступен для обучения будущих пользователей SO.   -  person David C. Rankin    schedule 04.11.2015


Ответы (1)


Я не изучал ваш код подробно, но hsearch требует, чтобы время жизни ключей было не меньше, чем у htables, потому что он просто сохраняет запись как есть, не делая глубокую копию указателей.

Вы используете временный указатель для хранения текущего ключа; вы часто aprintf и free этот указатель. Во время второго поиска дескриптор уже недействителен. (Вы можете запустить код в Valgrind, чтобы найти такие ошибки доступа к памяти.)

Вероятно, вам может сойти с рук дублирование строки:

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

но это тоже не правильное решение, потому что когда вы уничтожаете htable, происходит утечка памяти для ключей.

Из man hsearch:

Функции hdestroy() и hdestroy_r() не освобождают буферы, на которые указывают элементы ключа и данных записей хэш-таблицы.

htable не владеет данными. Он просто обеспечивает быстрый поиск уже существующих данных, которыми вы должны управлять самостоятельно. (У него есть и другие ограничения: максимальное количество записей должно быть известно заранее, и элементы нельзя удалять.)

person M Oehm    schedule 04.11.2015
comment
@M Оэм: Спасибо. вы, вероятно, правы, потому что он просто сохраняет запись как есть, не делая глубокую копию указателей. С ограниченными знаниями, которые у меня были, мне удалось понять это поведение. Я думаю, что uthash намного лучше реализует хэш-таблицу. Используя это, я мог заставить inotifywait делать то, что хотел. Но мне пришлось снова сделать strdup, как вы предложили, даже в юташе. Я постараюсь прочитать больше, чтобы увидеть, как я могу освободить память. - person venkrao; 05.11.2015
comment
Да, uthash хорошо выглядит. Вы можете перебирать элементы — то, что вы не можете сделать с hsearch- и free всеми строками до уничтожения хеш-таблицы. Функция delete_all в примере показывает это. - person M Oehm; 05.11.2015