Следующая игрушечная программа работает корректно (ну, не выполняет segfault *, по крайней мере, 1002 *) с определениями и функциями, которые вы опубликовали:
#include <stdlib.h>
#include <assert.h>
/* code from question omitted */
int main(void)
{
HashTable * hash = initHashTable(5);
int i;
assert(hash->size == 5);
for ( i = 0; i < hash->size; i++ )
assert(hash->table[i] == NULL);
free(hash);
return EXIT_SUCCESS;
}
Я полагаю, что вышеприведенное верно, чтоВы считаете NULL-указатель «пустым» списком, верно?(Таким образом, функция insert
заменит соответствующий NULL первым элементом нового списка.)
Если это так, вы можете значительно упростить ситуацию.Можно написать инициализатор, который заставит вышеуказанную игрушечную программу работать через valgrind.Я не хочу вас обманывать, но могу вам сказать, что вы можете посмотреть, что такое гибкие массивы и как они работают.
Игнорирование проблем в функции инициализации (valgrind должен довольно точно сказать вам, что не так, если у вас есть приложение, а не segfaulting), каковы границы для функции hash()
в функции поиска?
Вы пытаетесь прочитать значение hashtable->table[hash(number)]
, поэтому hashtable
необходимо инициализировать хотя бы с таким количеством элементов, в противном случае вы будете читать из памяти, которую вы не распределили (отсюда ошибка сегментации).
Возможно, вы имели в виду
List * lookup(HashTable *hashtable, char *number)
{
assert(hashtable != NULL);
assert(number != NULL);
unsigned int hashval = hash(number) % hashtable->size;
List * list = hashtable->table[hashval];
assert( list == NULL || list->number != NULL );
while ( list != NULL && strcmp(number,list->number)!=0)
{
list = list->next;
assert ( list == NULL || list->number != NULL );
}
return list;
}
Обновления: вы не можете передать нулевой указатель на strcmp
из журнала Valgrind, который вы опубликовали, что является причиной возникновения ошибки сегментации.Функция поиска, представленная выше, была обновлена с некоторыми другими утверждениями, чтобы убедиться, что этого не происходит.
Кроме того, valgrind намекает, что вы передали неинициализированное значение в strcmp
, это может быть нулевой указатель (если неинициализированное значение обнуляется).Тем не менее, по-прежнему не хватает важной информации, чтобы правильно ответить на этот вопрос. Не могли бы вы опубликовать весь файл hash.c
где-нибудь?
После прочтения файла: я должен быть честным, у вас есть очень серьезныепроблемы в этом коде :-) Я думаю, вы еще не поняли концепцию ручной обработки и инициализации памяти - возможно ли, что вы сначала изучили Java?
В любом случае, вот проблемы, которые я определяю в произвольном порядке:
- В
init_array_for_antennas()
вы инициализируете локальную переменную MyArray, а не глобальные .Просто удалите локальную переменную, и все будет в порядке. - Статические и глобальные переменные неявно инициализируются нулем, поэтому почти все в
init_array_for_antennas()
просто избыточно. - В некоторых местах вы «инициализируете» указатели с помощью
malloc()
, а затем устанавливаете указатель на его фактическое значение.Это классическая утечка памяти;вы не сможете освободить такую память, поскольку перезаписываете ссылку на нее. - Оператор
number[strlen(number)]='\0';
, ну, просто избыточен.Подумайте о том, как работает strlen (), и вы сами должны это увидеть. - Если вы еще этого не сделали, прочитайте, что такое утверждения, и узнайте, как их использовать, чтобы проверить свои предположения.Комментировать
assert(pointer_you_dereference_later != NULL);
просто неправильно. - Если у вас уже есть указатель на строку, вам не нужно копировать содержимое в локальный массив, а затем передавать этот массив базовым функциям - просто передайте указатель!
- В некоторых местах вы используете глобальную константу
bucket_size
, а в других - поле структуры хеш-таблицы size
.Эта ошибка просто ожидает, либо сделайте поле размера фактической константой времени компиляции, либо правильно используйте значение времени выполнения. - На самом деле вопрос стиля, но вы вводите большую часть struct в красивые, понятные человеку имена, и, тем не менее, в любом случае добавляете ключевое слово struct.
- Если вы используете
calloc()
вместо malloc()
, вы получите нулевую память.Например, выделение массива указателей с calloc()
сделает их инициализированными в NULL, и вам не нужно делать это явно.
Что ж, возможно, есть еще кое-что, но на сегодня все.Я предполагаю, что первая точка в списке является причиной вашей реальной проблемы: -)