HashTable中的内存分配问题

请不要关闭这个说一个重复的问题 。 我做了一个重要的改变,所以不要混淆别人,我重新提交了这个更清晰的代码。

请帮我解决这个内存分配问题。 我正在研究一个HashTable,这就是我的(仅限部分代码)

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; hash->list = (ListPtr *)calloc(capacity, sizeof(List)); /*NO MEMORY ALLOCATION HERE*/ return hash; 

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 *); }; ... ... 

当我运行我的调试器(Netbeans C / C ++调试器,我看到没有内存被分配给hash-> list。在上面的例子中,我的尝试是使它成为10个列表的数组。

请帮我解决这个问题。

如果有帮助的话,我不是C的专家。

这条线

 hash = (HashTablePtr) malloc(sizeof(HashTablePtr)); 

应该读

 hash = (HashTablePtr) malloc(sizeof(HashTable)); 

我还建议你按照上一篇文章中给出的建议,不要通过typedef’ing隐藏指针。 只需使用List *

[每当你看到一个alloc语句时,你指定的类型是一个指针,你分配的类型应该是类型(而不是指向类型的指针)]

你可以使用的一个很好的习语是:

 hash = (HashTablePtr) malloc(sizeof(*hash)); 

通过不对分配中的任何类型进行硬编码,大大减少了混合的可能性。

请注意,’hash’实际上并未在此处取消引用 – sizeof()始终在编译时进行求值,因此编译器只需确定* hash / will / have的类型,并获取其大小。

在这一行:

 hash->list = (ListPtr *)calloc(capacity, sizeof(List)); 

calloc函数将为List分配一些内存,然后返回一个指向已分配内存的指针,该内存为List* (或者,由于typedef ,相当于ListPtr )。

在代码中,指针然后被转换为(ListPtr*) ,它实际上是List** ,它不是期望的类型List* 。 因此,将ListPtr*更改为ListPtr并查看是否可以修复该行。

编辑

正如leiz和Klathzazt在评论中指出的那样, Hashtable.list类型是ListPtr*List**

 struct hashtable { ... ListPtr *list; 

这就是为什么尝试分配从calloc返回并从ListPtr类型会导致编译器错误的原因。 它不应该存储指向Hashtable List的指针的指针,而应该只保存指向列表的指针:

 struct hashtable { ... ListPtr list; 

这应该消除编译器错误,因为Hashtable.list和类型转换的类型都将是ListPtr

就个人而言,我不是使用typedef的忠实粉丝,特别是当你是初学者时。 我认为这可能部分令你感到困惑。 你最好避免以下事情:

 typedef struct hashtable * HashTablePtr; 

使用许多typedef会使你的代码更难阅读,因为你需要经常查找他们所指的内容。

主要问题是您为哈希表/列表指针的大小分配内存,而不是为其受尊重的结构的大小。 我认为下面的代码很好地展示了这一点。 您还需要检查分配是否有效。 如果是malloc,calloc,realloc。 等失败他们返回NULL。 如果发生这种情况并且您没有检查此情况,则会出现段错误,程序将崩溃。

还要遵循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);