Почему этот код не выделяет память в C? - PullRequest
0 голосов
/ 06 мая 2009

Обновленный вопрос здесь

Проблема выделения памяти в HashTable

Я работаю над созданием HashTable на C. Это то, что я сделал. Я думаю, что я иду по правильному пути, но когда я пытаюсь

main.c

HashTablePtr hash;
hash = createHashTable(10);
insert(hash, "hello");
insert(hash, "world");

HashTable.c

    HashTablePtr createHashTable(unsigned int capacity){
    HashTablePtr hash;
    hash = (HashTablePtr) malloc(sizeof(HashTablePtr));
    hash->size = 0;
    hash->capacity = capacity;
    ListPtr mylist = (ListPtr)calloc(capacity, sizeof(ListPtr)); /* WHY IT DOESN'T ALLOCATE MEMORY FOR mylist HERE?? */
    mylist->head = NULL;
    mylist->size = 0;
    mylist->tail = NULL;    
    hash->list = mylist;  
    return hash;

ListPtr является списком LinkedList

list.h

typedef struct list List;
typedef struct list * ListPtr;

struct list {
    int size;
    NodePtr head;
    NodePtr tail;
};
...
...

HashTable.h

    typedef struct hashtable * HashTablePtr;
    typedef struct hashtable HashTable;
    struct hashtable {
        unsigned int capacity;
        unsigned int size;
        ListPtr *list;
        unsigned int (*makeHash)(unsigned int, void *);
    };
...
...

Когда я запускаю свой отладчик, я не вижу выделенной памяти для myList. В приведенном выше примере я пытаюсь создать массив из 10 списков.

Пожалуйста, помогите мне решить эту проблему.

Я не такой эксперт в Си, если это поможет.

Ответы [ 4 ]

2 голосов
/ 06 мая 2009

Лично я не большой поклонник использования typedefs, особенно когда вы новичок. Я думаю, что это может быть отчасти то, что вас смущает. Вам лучше избегать таких вещей, как:

typedef struct hashtable * HashTablePtr;

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

Основная проблема заключается в том, что вы выделяете память для размера указателя хеш-таблицы / списка, а не для размера их уважаемых структур. Я думаю, что код ниже показывает это хорошо. Вы также захотите проверить, сработали ли ваши распределения. Если malloc, calloc, realloc. и т.д. терпят неудачу, они возвращают NULL. Если это произойдет, и вы не проверите этот случай, вы получите ошибку segfault, и ваша программа потерпит крах.

Также следуйте стандарту c99 и поместите все объявления переменных в начало функции.

c99 std

Руководство пользователя malloc

struct hashtable *
createHashTable(unsigned int capacity){
    struct hashtable *hash;
    struct list *mylist;

    /* You want to allocate size of the hash structure not the size of a pointer. */
    hash = malloc(sizeof(struct hashtable)); 
    // always make sure if the allocation worked.
    if(hash == NULL){
        fprintf(stderr, "Could not allocate hashtable\n");
        return NULL;
    }

    hash->size = 0;
    hash->capacity = capacity;

    /* Unless you need the memory to be zero'd I would just use malloc here
     * mylist = calloc(capacity, sizeof(struct list)); */
    mylist = malloc(capacity * sizeof(struct list));
    if(mylist == NULL){
        fprintf(stderr, "Could not allocate list\n");
        free(hash); /* free our memory and handle the error*/
        return NULL;
    }

    mylist->head = NULL;
    mylist->size = 0;
    mylist->tail = NULL;    
    hash->list = mylist;

    return hash;
}

Также не забудьте освободить свой список, прежде чем освободить свою хеш-таблицу:

free(myhash->list);
free(myhash);
2 голосов
/ 06 мая 2009
calloc(capacity, sizeof(ListPtr)

должно быть

calloc(capacity, sizeof(List)
2 голосов
/ 06 мая 2009

Я думаю, что здесь есть целый ряд проблем. Вы не включили полученную ошибку, я перечислю пару:

  • hash = (HashTablePtr) malloc (sizeof (HashTablePtr *)); - Вы выделяете размер HashTable **, который составляет четыре байта, вам необходимо выделить размер базового объекта.
  • ListPtr mylist = (ListPtr *) calloc (емкость, размер (ListPtr)); - Опять же, вы выделяете размер указателя, а не базовый объект списка.
  • HashTablePtr createHashTable (unsigned intacity)) {- Вы, вероятно, получаете здесь ошибку компиляции с дополнительными паренами и несовместимым числом параметров.
0 голосов
/ 06 мая 2009

Вы выделяете непрерывный блок ListPtr, но вы действительно хотите выделить пространство для всех структур, а не только указатели (ListPtr) для этих структур:

calloc(capacity, sizeof(List));

Я согласен с комментарием gman о том, что не нужно прятать указатели. При кодировании на C я никогда не набираю List * как ListPtr. Это усложняет понимание кода.

...