C programming trie tree insert - c

I just started programming and have a beginner question,I am writing a trie insert function that insert a string into the trie tree. But when I add a string with more than two characters I'm getting heap buffer overflow. Here is my insert function:
struct node* insert(struct node *root,char *c){
int i=0;
struct node *temp=root;
while(c[i]){
int index=c[i]-'a';
//New Node
struct node *n=malloc(sizeof(*n));
n=malloc(sizeof(struct node));
temp->child[index]=n;
i++;
temp=temp->child[index];
}
return root;
};
The definition of the tree node
struct node
{
int isword;
int prefix;
int occurrence;
int leaf;
struct node * child[26];
};
and How I called them
char *c=malloc(3*sizeof(char));
c[0]='a';
c[1]='d';
c[2]='e';
struct node *root=malloc(sizeof(*root));
root=malloc(sizeof(struct node));
insert(root,c);
I think it's how I allocate space in the insert function for new node that went wrong, but I'm not sure what's the proper way to avoid heap buffer overflow, any advice please?

c is not ending with nul. So c[i] is undefined if i>=3(maybe coredump because access invalid memory address). while(c[i]) may run more than 3 times. This maybe the point.
char *c=malloc(3*sizeof(char));
c[0]='a';
c[1]='d';
c[2]='e';
btw, code below will cause memory leak:
struct node *root=malloc(sizeof(*root));
root=malloc(sizeof(struct node));

Related

I am using malloc() to allocate a pointer (8bytes) but it's able to store the whole node (16bytes). How?

What I did :
I added a pointer in the parameter of malloc(struct Node *) which is usually malloc(struct Node).
Problem :
When I am allocating memory for the size of a pointer then how the code is working?
malloc() is allocating 8 bytes of memory and returning the pointer
So the pointer points to an 8 bytes memory block which but further I am storing more data in it.
struct Node
{
int data;
struct Node *next;
};
struct Node *GetNode(int data)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node *));
node->data = data;
node->next = NULL;
return node;
}
Difference in size:
I know that malloc is allocating different sizes because I did this
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void main(){
int i = sizeof(struct Node);
int j = sizeof(struct Node *);
printf("%d,%d", i, j);
}
Output
16,8
What you've done is undefined behavior. It could work (on some systems, on certain days of the week), or it could crash, or it could produce incorrect results in seemingly unrelated calculations.
Imagine you rent a garage space for your truck, but to save money you request a space for a car. What happens when you drive your truck in? Maybe it fits, maybe you wreck the truck, maybe you destroy the garage.
So don't do that, and to help you find cases where you've made similar mistakes, build with Address Sanitizer. It will log when you access memory in an invalid way.
UB is a fickle mistress. Sometimes agreeable; sometimes not.
That is why you should use a syntax that makes it less likely to make mistakes:
struct Node *node = (struct Node *)malloc(sizeof(struct Node *)); // bad
struct Node *node = malloc( sizeof *node ); // good
No casting, and no redundancy.
I would even recommend using typedef's to free yourself from "struct, struct, struct".
typedef struct s_node
{
int data; // use more indentation, please. whitespace is cheap.
struct s_node *next;
} Node_t;
/* ... */
Node_t *node = malloc( sizeof *node ); // better
Finally, a lot of hours are wasted tracking down bugs that appear and disappear. Until performance becomes a real issue that you understand, I'd recommend using calloc() as the go-to allocation function:
Node_t *node = calloc( 1, sizeof *node ); // best
You can sleep easier knowing the byte values will be repeatable from run to run.

C programming free trie tree

I just started programming and I have a beginner question:
So I have a trie tree and I want to use it to store a large numbers of words from multiple files.
In order to do that everytime after I insert all the words from one file into the tree, I need to free the memory of the tree so that I can reuse the tree for the next file.
Should I use free to just free the root? Or I need to traverse the tree and delete all the node one by one?
Here's the node, I am already able to insert all the words into the tree.
struct node{
struct node * parent;
int noempty;
int isword;
int super;
int occurrence;
int leaf;
struct node * child[26];
};
Here is my insert function:
struct node* insert(struct node *root,char *c){
int i=0;
struct node *temp=root;
int l=length(c);
while(i!=l){
int index=c[i]-'a';
if(temp->child[index]==NULL){
//New Node
struct node *n=(struct node *)malloc(sizeof(struct node));
n->parent=temp;
temp->child[index]=n;
temp->noempty=1;
}
//Node Exist
if(i!=l&&temp->leaf==1){temp->leaf=0;}
temp=temp->child[index];
i++;
}
if(temp->noempty==0){
temp->leaf=1;}
temp->isword=1;
return root;
};
You must traverse the tree and free every node. Each node you created for the Trie has been dynamically allocated. If you just delete the root, then only the memory for the root will be freed, while the memory for every other node is taking up space in the heap. This means you have a memory leak. If you create a Trie for each of your files, the memory that you have not freed could add up to be a substantial amount.

Segmentation fault with char array member of struct using strcpy()

I have a struct TREE defined this way:
typedef struct TREE {
NODE *head;
} TREE;
and a struct NODE defined as:
typedef struct NODE {
char boss[30];
char name[30];
struct NODE *firstChild;
struct NODE *secondChild;
struct NODE *thirdChild;
struct NODE *fourthChild;
} NODE;
In my main, I have:
TREE companyStructure;
TREE *treeptr;
treeptr = &companyStructure;
strcpy(treeptr->head->name, "Ben");
But this gives me a segmentation fault. Can someone help me explain why this is the case? Is there some memory management that I'm not doing that I need to be doing?
Till,
treeptr = &companyStructure;
Things look good. But then considering the fact that you have
NODE *head;
you need to allocate memory for head. So most likely you've missed
treeptr->head = malloc(sizeof *treeptr->head);
before doing
strcpy(treeptr->head->name, "Ben");
Also, check [ this ] on why should you use strncat instead of strcpy.

What is the reason for this segmentation fault in this Linked List program?

This program always gives me a Segmentation Fault when I add the last node, what could be the possible reason. it only comes while adding the last node, I have commented the line in which I get the segmentation fault.
I'm new to programming.
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
struct node *createNode(int val){
struct node *ret=(struct node *)malloc(sizeof(struct node));
ret->data=val;
ret->next=NULL;
return ret;
}
struct node *addNode(struct node *ll,int val){
//Gives error here for the last node, it creates the node succesfull but this step give segmentation fault
struct node *new_node=createNode(val);
new_node->next=ll;
return new_node;
}
void printList(struct node *ll){
printf("printing list");
struct node *temp=ll;
while(temp->next){
printf("%d ->",temp->data);
temp=temp->next;
}
}
int main(){
struct node *head;
head=addNode(head,3);
head=addNode(head,5);
head=addNode(head,1);
head=addNode(head,9);
printList(head);
}
struct node *head;
head is uninitialized so using uninitialized variables leads to undefined behavior. Initialize your head to NULL before adding nodes.
struct node *head = NULL;
DO NOT CAST MALLOC AND FAMILY
Assign NULL to the head.
struct node * head=NULL;
because in addnode you are doing like this,
new_node->next=ll;
Then while printing the node make the condition like this,
while(node){
...
}
If you use the node>next you will loss the last value in the linked list.
Don't cast the malloc and family.
you are facing this problem because when you are adding the new node in the link list you are adding this node as a start of the linklist.
Initially:
struct node* head; //This is not NULL.Big mistake by you.But this is not the only problem.
The segmentation fault is there because you are trying to access the invalid memory location in printList(), as the last node pointer( which was firstly declared by you as head) is not pointing to any valid memory location.Try commenting the call to printList() you will see that bug goes.But this is not the solution you are looking for, even if you initialize the head to NULL you will face the problem where last node will not get printed.for this use:-
while(temp)
in printList().

Allocating space to a node pointer

I am currently attempting to use a doubly linked list to sort some data. I am having trouble creating a new node with the given data. Below was the code given to me:
#ifndef LIST_H_
#define List_H_
#define MAX_SYMBOL_LENGTH 7
struct order {
int id;
char symbol[MAX_SYMBOL_LENGTH];
char side;
int quantity;
double price;
};
typedef struct order* OrderPtr;
typedef struct onode* NodePtr;
struct onode {
OrderPtr data;
NodePtr next;
NodePtr prev;
};
This is the code that I have written using list.h as a header.
Here is the code that seemingly keeps crashing:
#include "list.h"
NodePtr newNode(OrderPtr data){
NodePtr node = (NodePtr)malloc(sizeof(NodePtr));
//node->data = (NodePtr)malloc(sizeof(OrderPtr));
//*node->data = *data;
node->data = data;//This is the one I am having problems with
node->next = NULL;
node->prev = NULL;
return node;
}
It compiles fine but when I try and submit it to an online grader it says that it does not work.
Here is my thought process,
create memory for NodePtr.
create memory for NodePtr->data.
and then assign the values of data passed from the function to the values in Node->Ptr.
But I do not know how to allocate memory for NodePtr->data.
NodePtr node = (NodePtr)malloc(sizeof(NodePtr));
Isn't doing what you are thinking. It's allocate space to hold a pointer same as sizeof(int*), it's 4 bytes on 32-bit machine, usually.
You need to do NodePtr node = malloc(sizeof(struct onode)); instead of.
data member should be result to a malloc(sizeof(struct order));
Also, don't cast result value from a malloc() call.
NodePtr is a pointer to a node and not the node itself. You're only allocating enough memory for a pointer and not all the members of the onode structure. You'll want to call malloc with sizeof(struct onode).

Resources