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);
}
Related
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.
Basically I made a create_app() function to allocate 2 nodes in the stack, each having a pointer to an array[max]; undo() pops the last element, and before returning it, it adds it into the REDO node's array. redo() does the opposite, pops the last element in it's array, putting it into Undo's array before returning it. What did I do wrong ?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node *node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack != NULL){printf("Out of space!");}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return(S->tos==-1);
}
int
isFull(STACK S)
{
return(S->tos>=S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
int
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
int
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Some small errors were in your code, like these ones in create_app() which seem like typos.
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
^
|
if(UNDO->arr_stack != NULL){printf("Out of space!");}
^
|
...
and some int returning functions did not return anything in the else part which gave some warnings.
Here is the modified code, which worked fine for me
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node* node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack = (int *) malloc(max * sizeof(int));
REDO->arr_stack = (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack == NULL){printf("Out of space!");
return NULL;}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return (S->tos == -1);
}
int
isFull(STACK S)
{
return (S->tos >= S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
void
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
void
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Result:
3223
However, always take precaution in deallocating the memory malloced using free().
I am practicing the Leetcode question "Next Greater Node in Linked List"
and here is my code:
#define STACK_SIZE (10000U)
typedef struct ListNode Node;
static int stack[STACK_SIZE];
static int top=-1;
bool isEmpty()
{
return (top==-1);
}
void addToStack(int element)
{
stack[++top]=element;
}
void remFromStack()
{
--top;
}
int getStackTop()
{
return stack[top];
}
typedef struct ListNode Node;
int* nextLargerNodes(struct ListNode* head, int* returnSize) {
if (head == NULL) {
*returnSize = 0;
return NULL;
}
int len = 0;
Node *temp = head;
while (temp) {
len++;
temp = temp->next;
}
if (len > 0) {
int *result = malloc(len * sizeof(int));
*returnSize = len;
if (result == NULL) {
return NULL;
}
int j = 0;
while (j < len) {
result[j++] = 0;
}
temp = head;
addToStack(temp->val);
j = 0;
while (temp->next) {
temp = temp->next;
j++;
if (getStackTop() > temp->val) {
addToStack(temp->val);
} else {
int i = 0;
while (!isEmpty()) {
i++;
result[j - i] = temp->val;
remFromStack();
}
addToStack(temp->val);
}
}
return result;
} else {
return NULL;
}
}
And I am getting the following error:
=================================================================
==29==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6030000
WRITE of size 4 at 0x60300000000c thread T0
#2 0x7f55143382e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.s
0x60300000000c is located 4 bytes to the left of 20-byte region [0x60300
allocated by thread T0 here:
#0 0x7f55157c22b0 in malloc (/usr/local/lib64/libasan.so.5+0xe82b0)
#3 0x7f55143382e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.s
I am not sure what's wrong here.
Tried making sure all the code is correct, and when I test the code against my own test cases, it works perfectly fine, but when I submit the code, only then I am getting this error.
Note: The returned array must be malloced, assume caller calls free().
The utility functions dont have any malloc/ calloc called in them, so, that removes them from the equation.
Sizeof behaves differently on Leetcode.
Try to use strlen (if you are using char) OR other methods to find the size of a datatype you are trying to use.
struct NODE{
double theta, phi;
int ID;
int pointer;
};
int main(void)
{
FILE *fp;
int ID[5000][5000];
struct NODE node[5000*5000];
struct NODE node2[5000*5000];
int elem[5000][8];
int tempID;
for(i=0; i< 5000*5000; i++){
node[i].theta = 0;
node[i].phi = 0;
}
for(k=0; k<5000; k++){
for(j=0; j< 5000; j++){
ID[k][j] = -1;
}
}
}
This is a part of the source code of my project. here i want to allocate memory in this lines using malloc. How can i do this??
struct NODE node[5000*5000];
struct NODE node2[5000*5000];
You need to call malloc in the following manner:
struct NODE *node, *node2;
node = malloc(5000*5000*sizeof(*node));
if (node == NULL)
{
exit(1); // or any other error check
}
node2 = malloc(5000*5000*sizeof(*node));
if (node2 == NULL)
{
exit(1); // or any other error check
}
Rest of the code will be unchanged.
I am trying to take input from console and add it to hash table.
But I'm getting Segmentation fault 11.
So, I debugged the program using gdb-apple.
It is showing that I'm trying access memory I cannot, using the pointer variable.
I think it is something obvious, but I'm missing it
This is what the gdb is displaying
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000986 in CreateHashTable (size=200) at hashing.c:29
29 h->Table[i]->next = NULL;
Here is the code
Header File:
#define LOAD_FACTOR 20
#define INITIAL_SIZE 200
struct HashTable *CreateHashTable(int size);
int HashSearch(struct HashTable *h,int data);
int HashInsert(struct HashTable *h,int data);
int HashDelete(struct HashTable *h, int data);
void Rehash(struct HashTable *h);
int Hash(int data, int size);
struct ListNode
{
int key;
int data;
struct ListNode *next;
};
struct HashTableNode
{
int bcount;
struct ListNode *next;
};
struct HashTable
{
int tsize;
int count;
struct HashTableNode **Table;
};
Implementation file:
#include "hashing.h"
#include<stdio.h>
#include<stdlib.h>
struct HashTable *CreateHashTable(int size)
{
struct HashTable *h;
h = (struct HashTable *) malloc ( sizeof(struct HashTable) );
if(h == NULL)
{
printf("Memory Error");
return NULL;
}
h->tsize = (int) size/LOAD_FACTOR;
printf("h->tsize = %d",h->tsize);
h->count = 0;
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
if( h->Table == NULL )
{
printf("Memory Error");
return NULL;
}
int i;
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
return h;
}
I would paste the rest of file, or Driver file, but I don't see it relevant.
Please tell me why I'm getting the segmentation fault 11
You allocated memory for array of pointers but you didn't allocate memory for members of this array.
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i] = malloc(...); //put correct arguments here and check allocation
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
Your problem is here:
struct HashTableNode **Table;
You want an array of nodes (not a 2d array), change to:
struct HashTableNode *Table;
also change
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
to
h->Table = malloc(sizeof(struct HashTableNode) * h->tsize);
I think I want an array of pointers to nodes, don't I?
As pointed out by #WhozCraig, there is no reason for the additional level of indirection.
Example A (Pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a; /* pointer */
int i, n = 10;
a = malloc(n * sizeof(int)); /* space for 10 ints */
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Example B (Pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **a; /* pointer to pointer*/
int i, n = 10;
a = malloc(n * sizeof(int *)); /* space for 10 pointer to ints */
for (i = 0; i < n; i++) {
a[i] = malloc(sizeof(int)); /* space for 1 int */
*a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", *a[i]);
free(a[i]);
}
free(a);
return 0;
}
As you can see both do the same thing, but the first one requires less memory and the code is cleaner.
One way to make it easy to remember is:
int * can hold an array
int ** can hold a table (NROWS * NCOLS)
int *** can hold an array of tables