请不要将此duplicate question关闭。我做了一个重要的改变,所以不要混淆别人,我重新提交了这个更清晰的代码。
请帮我解决这个内存分配问题。我正在研究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->列表。在上面的例子中,我的尝试是使它成为10个列表的数组。
请帮我解决这个问题。
如果有帮助的话,我不是C的专家。
答案 0 :(得分:4)
这一行
hash = (HashTablePtr) malloc(sizeof(HashTablePtr));
应该阅读
hash = (HashTablePtr) malloc(sizeof(HashTable));
我还建议您按照上一篇文章中给出的建议,而不是通过typedef'ing隐藏指针。只需使用List *
[每当你看到一个alloc语句时,你指定的类型是一个指针,你要分配的类型应该是类型(而不是指向该类型的指针)]
答案 1 :(得分:4)
你可以使用的一个很好的习语是:
hash = (HashTablePtr) malloc(sizeof(*hash));
通过不对分配中的任何类型进行硬编码,大大减少了混合的可能性。
请注意,'hash'实际上并未在此处取消引用 - sizeof()始终在编译时进行评估,因此编译器只需计算出* hash / will / have的类型,并获取其大小。
答案 2 :(得分:1)
在这一行:
hash->list = (ListPtr *)calloc(capacity, sizeof(List));
calloc
函数将为List
分配一些内存,然后返回指向已分配内存的指针,该内存为List*
(或相当于ListPtr
,因为typedef
。)
在代码中,指针随后被转换为(ListPtr*)
,其实际上是List**
,而不是预期的类型List*
。因此,请将ListPtr*
更改为ListPtr
并查看是否可以修复该行。
修改强>
正如leiz和Klathzazt在评论中指出的那样,Hashtable.list
类型为ListPtr*
或List**
:
struct hashtable {
...
ListPtr *list;
这就是为什么尝试分配从ListPtr
返回并转换的calloc
类型会导致编译器错误的原因。它不是存储指向Hashtable
中List的指针的指针,而应该只保存指向列表的指针:
struct hashtable {
...
ListPtr list;
这应该消除编译器错误,因为Hashtable.list
和类型转换的类型都是ListPtr
。
答案 3 :(得分:0)
就我个人而言,我并不是使用typedef的忠实粉丝,特别是当你是初学者时。我认为这可能部分令你感到困惑。你最好避免这样的事情:
typedef struct hashtable * HashTablePtr;
使用许多typedef会使你的代码更难阅读,因为你需要经常查找他们所指的内容。
主要问题是您为哈希表/列表指针的大小分配内存,而不是为其受尊重的结构的大小分配内存。我认为下面的代码很好地说明了这一点。您还需要检查分配是否有效。如果是malloc,calloc,realloc。等失败,他们返回NULL。如果发生这种情况并且您没有检查此情况,则会出现段错误,程序将崩溃。
同样遵循c99标准,并将所有变量声明放在函数的开头。
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);