Valgrind shows blocks are definitely lost in loss record - c

I can't understand why there's a memory leak in this code.
Data structures:
typedef struct linkedListNode_t {
int value;
struct linkedListNode_t* next;
struct linkedListNode_t* prev;
}linkedListNode_t;
typedef struct linkedList_t {
unsigned int size;
struct linkedListNode_t* head;
}linkedList_t;
typedef struct hashtableEntry_t {
struct linkedList_t* list;
} hashtableEntry_t;
typedef struct hashtable_t {
unsigned int size;
struct hashtableEntry_t** entry;
} hashtable_t;
typedef struct rbtNode_t {
int value;
char color;
struct rbtNode_t* parent;
struct rbtNode_t* left;
struct rbtNode_t* right;
} rbtNode_t;
typedef struct rbt_t {
unsigned int size;
struct rbtNode_t* root;
struct rbtNode_t* nil;
} rbt_t;
The free functions that i use:
void linkedListFree(linkedList_t* list) {
linkedListNode_t *node = list->head;
linkedListNode_t *victim;
while (node != NULL) {
victim = node;
node = node->next;
free(victim);
}
list->head=NULL;
free(list);
}
void hashtableFree(hashtable_t* hashtbl) {
int i;
if(!hashtbl)
return;
for(i=0;i<hashtbl->size;i++){
linkedListFree(hashtbl->entry[i]->list);
free(hashtbl->entry[i]);
hashtbl->entry[i]=NULL;
}
free(hashtbl);
hashtbl=NULL;
}
void rbtFreeNodes(rbt_t* T, rbtNode_t* x) {
if(x == T->nil)
return;
rbtFreeNodes(T,x->left);
rbtFreeNodes(T,x->right);
free(x);
}
void rbtFree(rbt_t* T) {
rbtFreeNodes(T,T->root);
free(T);
T = NULL;
}
This is the message Valgrind gives to me:
==28711== 76,800 bytes in 2,400 blocks are definitely lost in loss record 4 of 5
==28711== at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==28711== by 0x10A026: createRbt
==28711== by 0x10AB76: doExperiment
==28711== by 0x1094BA: main
==28711==
==28711== 1,132,800 bytes in 2,400 blocks are definitely lost in loss record 5 of 5
==28711== at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==28711== by 0x109BBE: createHashtable
==28711== by 0x10AA89: doExperiment
==28711== by 0x10949D: main
This is my doExperiment function:
clock_t doExperiment(int* randomArray, const unsigned int numInsertions, const unsigned int numSearches, char* dataStructure) {
clock_t startTime=0, endTime=0,tot = 0;
if(strcmp(dataStructure,"hashtable")==0){
hashtable_t *ht = createHashtable(NUM_ENTRIES);
linkedListNode_t *nodo;
startTime = clock();
for(int i=0;i<numInsertions;i++){
int randomIndex = rand() % numInsertions;
hashtableInsert(ht,randomArray[randomIndex]);
}
for(int i=0; i<numSearches;i++){
int randomIndex = rand() % numInsertions;
nodo = hashtableSearch(ht,randomArray[randomIndex]);
}
endTime = clock();
tot = endTime-startTime;
hashtableFree(ht);
}
if(strcmp(dataStructure,"rbt")==0){
struct rbt_t *rbt = createRbt();
struct rbtNode_t *nodo;
startTime = clock();
for(int i=0;i<numInsertions;i++){
int randomIndex = rand() % numInsertions;
nodo = createRbtNode(randomArray[randomIndex]);
rbtInsert(rbt,nodo);
}
for(int i=0;i<numSearches;i++){
int randomIndex = rand() % numInsertions;
nodo = rbtSearch(rbt,randomArray[randomIndex]);
}
endTime = clock();
tot = endTime-startTime;
rbtFree(rbt);
}
return tot;
}
As you can see i always call the free functions but i still have memory loss.
I can't figure out where my mistake is.
Are my free functions correct? Or they don't free the data structures? Any kind of help or suggestion is highly appreciated.

Related

Weird behaviour working on a skip list using void pointers

void insertSkipList(SkipList* list, void* I){
Node* new_node=createNode(I, randomLevel(list->max_level));
if (new_node->size > list->max_level)
Node* actual_node=list->head;
unsigned int k;
for (k = list->max_level;k>=1;k--){
if (actual_node->next[k] == NULL || list->compare(I, actual_node->next[k]->item)<0){
if (k < new_node->size) {
new_node->next[k] = actual_node->next[k];
actual_node->next[k]=new_node;
}
else{
actual_node->next = &actual_node->next[k];
k=k+1;
}
}
}
}
I'm having troubles with the command list->compare(I, actual_node->next[k]->item
as it doesn't execute at all. The problem is most likely here actual_node->next[k]->item but I can't see why.
These are the definitions of node and list
typedef struct _SkipList SkipList;
typedef struct _Node Node;
struct _SkipList {
Node *head;
unsigned int max_level;
int (*compare)(void*, void*);
};
struct _Node {
Node **next;
unsigned int size;
void *item;
};
The complete minimal reproducible example contained within the question itself is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LENGTH 20
#define MAX_HEIGHT 5
typedef struct _SkipList SkipList;
typedef struct _Node Node;
struct _SkipList {
Node *head;
unsigned int max_level;
int (*compare)(void*, void*);
};
struct _Node {
Node **next;
unsigned int size;
void *item;
};
unsigned int randomLevel(unsigned int height);
static int compare_int(void* x_void,void* y_void){
int x=(int)x_void;
int y=(int)y_void;
return x-y;
}
static Node* createNode(void* item, unsigned int lvl) {
Node* n = (Node*) malloc(sizeof(Node));
if(n == NULL) {
printf("\nError! Node memory not allocated.");
exit(0);
}
n->item = item;
n->next = NULL;
n->size = lvl;
return n;
}
SkipList* createSkipList(unsigned int height, int (*compare)(void*, void*)){
SkipList* skiplist = (SkipList*) malloc(sizeof(SkipList));
if(skiplist == NULL) {
printf("\nError! Skiplist memory not allocated.");
exit(0);
}
skiplist->head=createNode(NULL,height);
skiplist->max_level=1;
skiplist->compare=(*compare);
return skiplist;
}
void insertSkipList(SkipList* list, void* I){
Node* new_node=createNode(I, randomLevel(list->max_level));
if (new_node->size > list->max_level)
list->max_level = new_node->size;
Node* actual_node=list->head;
unsigned int k;
printf("here it's before the loop\n");
for (k = list->max_level;k>=1;k--){
if (actual_node->next[k] == NULL || list->compare(I, actual_node->next[k]->item)<0){ //here the code stops completely
if (k < new_node->size) {
new_node->next[k] = actual_node->next[k];
actual_node->next[k]=new_node;
}
}
else{
actual_node->next = &actual_node->next[k];
k=k+1;
}
}
printf("here it's after the loop (and actually this wont get printed idk why\n");
}
unsigned int randomLevel(unsigned int height){
unsigned int lvl = 1;
time_t t;
srand((unsigned) time(&t));
while (rand() < 0.5 && lvl < height)
lvl = lvl + 1;
return lvl;
}
int main() //creates a skiplist that goes from 0 to MAX_LENGTH
{
skiplist=createSkipList(MAX_HEIGHT,(*compare_int));
int found[MAX_LENGTH];
int expected[MAX_LENGTH];
for(int i=0;i<MAX_LENGTH;i++){
insertSkipList(skiplist,(void*) i);
}
return 0;
}

C - Separate Chaining Hash Table - Output and Space Issues

so basically I wrote a program to initialize, insert, and output the whole hash table. I thought I did pretty good, but there's many issues.
First issue being, some names are displayed with an additional weird character, why??
Second issue being, I can only input a size parameter (for initialize(size) function) of <8. Anything above 7 will output "Out of Space!" but why?? I thought I managed the space pretty well from what I was taught at uni:((
Please help!
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; i++)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr[i]=NULL;
}
return H;
}
position
set(const char *key, const char *value)
{
position entry = (position) malloc(sizeof(struct list_node));
entry->value = (char*) malloc(strlen(value)+1);
entry->key = (char*) malloc(strlen(key)+1);
strncpy(entry->key,key,strlen(key));
strncpy(entry->value,value,strlen(value));
entry->next = NULL;
return entry;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
node_ptr entry = H->list_ptr_arr[slot];
node_ptr prev;
if(entry==NULL)
{
H->list_ptr_arr[slot] = set(key, value);
return;
}
while(entry!=NULL)
{
if(strcmp(entry->key, key)==0)
{
free(entry->value);
entry->value = malloc(strlen(value)+1);
strncpy(entry->value,value,strlen(value));
return;
}
prev = entry;
entry = prev->next;
}
prev->next = set(key, value);
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
if(H->list_ptr_arr[i]==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", entry->key, entry->value);
if(entry->next == NULL)
{
printf("NULL");
break;
}
entry = entry->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(7);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Then I tried to change it up a bit:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!1"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!2"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; ++i)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!3"); return 0;}
H->list_ptr_arr[i]->value="HEAD";
H->list_ptr_arr[i]->next=NULL;
}
return H;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
LIST entry = H->list_ptr_arr[slot], newNode;
newNode = (position) malloc(sizeof(struct list_node));
if(newNode==NULL){printf("Out of Space4!"); return;}
newNode->next = entry->next;
strncpy(newNode->key,key,strlen(key));
strncpy(newNode->value,value,strlen(value));
entry->next = newNode;
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
position p = entry->next;
if(p==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", p->key, p->value);
if(p->next == NULL)
{
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Thank you!
I modified the second piece of code, it runs correctly on my computer.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 256
// typedefing struct list_node multiple times is confusing, so I remove these typedefs
struct list_node {
struct list_node *next;
// strings need storage space in the memory,
// declaring key and value as array here can save some calls to malloc()
char key[MAX_SIZE];
char value[MAX_SIZE];
};
struct hash_table {
struct list_node **list_ptr_arr;
unsigned int table_size;
};
// it's better not to hide pointer type using typedef
typedef struct hash_table HASHTABLE;
unsigned long long int hash(const char *key, unsigned int hash_size) {
// hash is not initialized originally (the value is choosed randomly)
unsigned long long int hash = 5;
for (int i = 0; key[i]; i++) {
hash = (hash << 32) + key[i];
}
return (hash%hash_size);
}
unsigned int next_prime(int number) {
int j;
for (int i = number; ; i++) {
for (j = 2; j < i; j++) {
if (i%j == 0) { break; }
}
if (i == j) { return j; }
}
}
HASHTABLE *initialize(unsigned int table_size) {
HASHTABLE *H;
// you don't need to type cast malloc() result in C
H = malloc(sizeof(*H));
H->table_size = next_prime(table_size);
// I suppose list_ptr_arr is a pointer to an array of struct list_node * object
H->list_ptr_arr = malloc(sizeof(*(H->list_ptr_arr)) * H->table_size);
for (unsigned int i = 0; i < H->table_size; ++i) {
// malloc() for H->list_ptr_arr only allocated area for struct list_node * array, the struct list_node pointed to is not allocated yet, so malloc() here
H->list_ptr_arr[i] = malloc(sizeof(*(H->list_ptr_arr[i])));
strcpy(H->list_ptr_arr[i]->value, "HEAD");
H->list_ptr_arr[i]->next = NULL;
}
return H;
}
void insert(const char *key, const char *value, HASHTABLE *H) {
unsigned int slot = hash(key, H->table_size);
struct list_node *entry = H->list_ptr_arr[slot], *newNode;
newNode = malloc(sizeof(*newNode));
newNode->next = entry->next;
// strlen() doesn't count the '\0', just use strcpy here
strcpy(newNode->key, key);
strcpy(newNode->value, value);
entry->next = newNode;
}
void dump(HASHTABLE *H) {
for (unsigned int i = 0; i < H->table_size; i++) {
struct list_node *entry = H->list_ptr_arr[i];
struct list_node *p = entry->next;
if (p == NULL) { continue; }
printf("slot[%d]: ", i);
for (;;) {
printf("%s|%s -> ", p->key, p->value);
if (p->next == NULL) {
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main() {
HASHTABLE *H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
P.S. Don't forget to free the hashtable.

Freeing a double pointer from a struct

I have a problem with my delete_table function. So i have 2 structs
struct _entry_ {
int key;
int data;
struct _entry_* next;
struct _entry_* prev;
};
typedef struct _entry_ entry;
struct _table_ {
entry** entries;
int size;
};
typedef struct _table_ table;
I initialise my table with calloc.
void table_init(table* ht, int initial_size) {
ht->entries = (entry**)calloc(initial_size, sizeof(entry*));
if (ht->entries) {
ht->size = initial_size;
}
}
Now my free function that i wrote
void table_destroy(htable* ht) {
entry *el, *temp;
int i;
for(i = 0; i < ht->size; i++) {
el = ht->entries[i];
while(el != NULL){
temp = el;
el = el->next;
free(temp);
}
free(ht->entries[i]);
}
free(ht); // <- don't know do i need this.
}
When i test it with valgrind i got this error
==13560== Invalid free() / delete / delete[] / realloc()
==13560== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13560== by 0x400783: htable_destroy (htable.c:46)
==13560== by 0x400A24: main (main.c:25)
==13560== Address 0xffefffae0 is on thread 1's stack
==13560== in frame #2, created by main (main.c:7)
Any help would be great, thank you for your time!
void table_destroy(htable* ht) {
entry *del;
int i;
for(i = 0; i < ht->size; i++) {
while( (del = ht->entries[i]) ) {
ht->entries[i] = del->next;
free(del);
}
}
free(ht->entries);
free(ht);
}

Segmentation fault when trying to access a function in from a user library

DoubleLinkedList.h
#ifndef _DOUBLE_LINKED_LIST_H
#define _DOUBLE_LINKED_LIST_H
typedef unsigned int uint;
typedef unsigned long ulong;
typedef void* Object;
typedef struct _DNode {
Object data;
struct _DNode* prev;
struct _DNode* next;
}DNode;
typedef struct _DoubleLinkedList{
DNode* head;
DNode* tail;
uint length;
uint elementSize;
}DoubleLinkedList;
DoubleLinkedList* allocDList (uint elementSize);
#endif
DoubleLinkedList.c
#include "DoubleLinkedList.h"
DoubleLinkedList* allocDList (uint elementSize)
{
DoubleLinkedList* l;
l->head = NULL;
l->tail = NULL;
l->length = 0;
l->elementSize = elementSize;
return l;
}
main.c
#include <stdio.h>
#include "DoubleLinkedList.h"
int main ()
{
DoubleLinkedList* ab;
ab = allocDList(10);
return 0;
}
When I try to run this I get a segmentation fault with a core dump.
this is what is required in the assignment.
DoubleLinkedList* allocDList(uint elementSize): this function allocates the DoubleLinkList
You haven't initialised l, so l->HEADwon't work. You can initialise it using malloc as:
DoubleLinkedList* l = malloc(sizeof(DoubleLinkedList));
Also, in the main function, once you are done using the variable ab, remember to release the memory used by it using the free function as follows:
int main ()
{
DoubleLinkedList* ab;
ab = allocDList(10);
//Processing here
free(ab); //Release once it is no longer needed
return 0;
}
DoubleLinkedList* l;
You need to allocate some memory to l
l = (DoubleLinkedList*) malloc(sizeof(DoubleLinkedList));
Update DoubleLinkedList.c as:
DoubleLinkedList* allocDList (uint elementSize)
{
DoubleLinkedList* l;
l = malloc(sizeof(DoubleLinkedList));
l->head = NULL;
l->tail = NULL;
l->length = 0;
l->elementSize = elementSize;
return l;
}

double pointer to struct inside struct

How can i access to a duble pointer in a struct pointer??
with the code bellow, calling addBow() give me a Segmentation fault (core dumped) error
typedef struct
{
int size;
tCity **cities;
}tGraph;
//para iniciar el grafo
void initGraph(tGraph *graph, int size)
{
graph = (tGraph*)malloc(sizeof(tGraph));
graph->cities = (tCity**)malloc(sizeof(tCity*) * size);
graph->size = size;
}
//agrega un arco entre ciudades
void addBow(tGraph *graph, int id, tCity *city)
{
if ( graph->cities[id] == NULL )
{
graph->cities[id] = city;
}
else
{
tCity *cur = graph->cities[id];
while ( getNext(cur) != NULL )
{
cur = getNext(cur);
}
setNext(cur, city);
}
}
which is the correct syntax for graph->cities[id]??
Thanks
SOLUTION:
editing the initGraph solve the problem since the memory wasn't allocated
tGraph* initGraph(int size)
{
tGraph *graph = (tGraph*)malloc(sizeof(tGraph));
graph->cities = (tCity**)malloc(sizeof(tCity*) * size);
graph->size = size;
return graph;
}
You should either have initGraph() take (**graph) or return the graph. Since the malloc address of graph is local to initGraph.
Something like:
void initGraph(tGraph **graph, int size)
{
tgraph *temp;
temp = (tGraph*)malloc(sizeof(tGraph*));
temp->cities = (tCity**)malloc(sizeof(tCity*) * size);
temp->size = size;
*graph = temp;
}
graph = (tGraph*)malloc(sizeof(tGraph*));
There is one of your problems...
it should be
graph = malloc(sizeof(tGraph));
Make initGraph () return a pointer to tGraph.
tGraph* initGraph(int size) {
tGraph* graph;
graph = malloc(sizeof(tGraph));
graph->cities = malloc(sizeof(tCity*) * size);
graph->size = size;
return graph;
}
//consider this example
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct test{
int val;
}test;
typedef struct data{
char ch[10];
test **p;
}data;
int main(){
data *d=malloc(sizeof(data));
strcpy(d->ch,"hello");
d->p=(test**)malloc(sizeof(test*));
d->p[0]=(test*)malloc(sizeof(test));
d->p[0]->val=10;
printf("%s,%d",d->ch,d->p[0]->val);
}

Resources