I use uthash hash table implementation with structs.
I have two hash tables, one of them (dataTable in code) collect some info in loop and when it finishes, save some of the data in the other hashtable (that is stuffTable). My program works(at least with small files) but when i check it with valgrind, it finds memory leaks for the second hash table(stuffTable) (but no leaks for the first table, eventhough i free it in same way)
==12075== Invalid read of size 8
==12075== at 0x111CEE: deleteTable (myTest.c:1456)
==12075== by 0x116AE6: getResults (myTest.c:1980)
==12075== by 0x117E69: packetLoop (myTest.c:2350)
==12075== by 0x1114C1: main (myTest.c:2872)
==12075== Address 0x8335498 is 40 bytes inside a block of size 96 free'd
==12075== at 0x4C2D16B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12075== by 0x111CE0: deleteTable (myTest.c:1458)
==12075== by 0x116AE6: getResults (myTest.c:1980)
==12075== by 0x117E69: packetLoop (myTest.c:2350)
==12075== by 0x1114C1: main (myTest.c:2872)
==12075== Block was alloc'd at
==12075== at 0x4C2DF55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12075== by 0x112046: getStuffs (myTest.c:1475)
==12075== by 0x116A75: getResults (myTest.c:1972)
==12075== by 0x117E69: packetLoop (myTest.c:2350)
==12075== by 0x1114C1: main (myTest.c:2872)
As you can see i only do malloc to create a new node and there are no other data structures in stuff struct for which i allocate memory. So i don't understand what causes memory leak. To delete hash table, i use standard procedure, given by uthash documentation:
void delete_all() {
struct my_struct *current_user, *tmp;
HASH_ITER(hh, users, current_user, tmp) {
HASH_DEL(users,current_user); /* delete; users advances to next */
free(current_user); /* optional- if you want to free */
}
}
And here is my code:
struct stuff {
u_int32_t key;
u_int32_t packets
u_int32_t bytes;
u_int32_t host;
char name[16];
UT_hash_handle hh;
};
struct stuff *myStuffTable = NULL;
struct key_data {
u_int32_t key;
u_int32_t packets;
u_int32_t bytes;
u_int32_t count;
struct triple top_host[A_SIZE];
UT_hash_handle hh;
};
struct key_data *dataTable = NULL;
struct triple {
u_int32_t host;
u_int32_t count;
char proto[16];
};
static void deleteTable(struct stuff *dataTable) {
struct stuff *current_key, *tmp;
HASH_ITER(hh, dataTable, current_key, tmp) { //(myTest.c:1456)
HASH_DEL(dataTable, current_key);
free(current_key); //(myTest.c:1458)
}
}
static void getStuffs(struct stuff **stuffTable, struct key_data *dataTable) {
struct stuff *s;
struct key_data *kd, *tmp;
struct triple inf;
HASH_ITER(hh, dataTable, kd, tmp) {
s = (struct stuff *)malloc(sizeof(struct stuff)); //(myTest.c:1475)
memset(s, 0, sizeof(struct stuff));
s->key = kd->key;
s->packets = kd->packets;
s->bytes = kd->bytes;
/* sort host array and take the first element */
qsort(&kd->hosts[0], A_SIZE, sizeof(struct triple), triple_cmp);
inf = kd->hosts[0];
if(((inf.count > THRESHOLD) {
s->host = inf.host;
strncpy(s->name, inf.name, sizeof(s->name));
}
else
s->host = 0;
HASH_ADD_INT(*stuffTable, key, s);
}
}
int main(){
.....
getStuffs(&myStuffTable, dataTable);
deleteTable(myStuffTable);
}