Why doesn't this code allocate memory in C?
Updated question here
Memory allocation problem in HashTable
I am working on creating a HashTable in C. This is what I did. I think I am on the right track, but when I try
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 - Link LinkedList ptr
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 *);
};
...
...
When I start my debugger, I don't see any memory being allocated for myList. In the example above, my attempt is to make it an array of 10 lists.
Please help me to solve this problem.
I'm not a C expert if that helps.
I think there are a number of problems here. You did not list the error you are getting, I have listed a couple:
- hash = (HashTablePtr) malloc (sizeof (HashTablePtr *)); - You allocate the size of the HashTable ** which is four bytes, you need to allocate the size of the underlying object.
- ListPtr mylist = (ListPtr *) calloc (capacity, sizeof (ListPtr)); - Again, you are allocating the size of the pointer, not the main object of the list.
- HashTablePtr createHashTable (unsigned int capacity)) {- You are probably getting a compilation error with extra parsers and inconsistent number of parameters.
a source to share
Personally, I'm not a big fan of using typedefs, especially when you're a beginner. I think this may be partially confusing for you. You are better off avoiding things like:
typedef struct hashtable * HashTablePtr;
Using typedefs in many will make your code harder to read, as you have to constantly look for what they refer to.
The main problem is that you were allocating memory for the size of the hashtable / list pointer, not the size of their respected structures. I think the code below shows this well. You will also want to check if you worked. If malloc, calloc, realloc. and so on, they don't return NULL. If this happens, and you don't check this case, you will get a segfault error and your program will crash.
Also follow the c99 standard and put all variable declarations at the beginning of the function.
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;
}
Also remember to free the list before freeing the hash table:
free(myhash->list);
free(myhash);
a source to share
You are allocating an adjacent ListPtr block, but you actually want to allocate space for all structures, not just pointers (ListPtr) for those structures:
calloc(capacity, sizeof(List));
I agree with gman's comment about non-hiding pointers. When coding in C, I never press a List *
like ListPtr
. This makes the code difficult to understand.
a source to share