I'm new to C and I just started learning how to use pointers. I'm trying to create a function (r) that adds to a bst depending on if the parameter (int n) is greater than the root nodes value. However, I keep getting segmentation fault (core dumped) after running the following code. How do I fix it so that it can run normally without error.
struct node {
int data;
struct node *left;
struct node *right;
}node;
struct node* newNode(int data){
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
void r (int n, struct node* root);
int main() {
struct node *root = newNode(1);
printf("%d", root->data);
r(10, root);
return 0;
}
void r(int n, struct node* root){
if(n > root->left->data){
root->right = newNode(n);
printf("New right is: %d\n", root->right->data);
}
else if(n < root->left->data){
int a = root->left->data;
root->left->data = n;
root->right->data = a;
printf("New left is: %d\n", root->left->data);
}
return;
}
In the r function you wrote:
root->left->data
But root->left is equal to NULL. This will cause a segfault because you can't dereference a null pointer.
You can check for validity by doing something like:
// Make sure the left node exists, then do the test after
if (root->left && root->left->data > n)
since doing root->left will cause it to check that it's non-zero (meaning not NULL).
Related
I'm new to C and this language is confusing me a bit.
I keep getting a segmentation fault 11 when running my quite simple linked list code:
struct node{
int val;
struct node *next;
};
struct node *init(){
struct node *l = NULL;
return l;
}
struct node *newNode(int val){
struct node* n = init();
n = (struct node*) malloc(sizeof(struct node));
n->val = val;
n->next=NULL;
return n;
}
void append(struct node* h, int val){
struct node *temp;
temp = h;
int i = 0;
while(temp->next != NULL){
temp = temp->next;
i++;
}
printf("TestAppend");
temp= newNode(val);
}
int main(){
struct node* l = init();
printf("Test1\n");
append(l, 15);
printf("Test2\n");
struct node* temp = init();
temp = l;
}
can someone please explain why?
Thanks :)
Try to change init function to:
struct node *init()
{
void* p = malloc(sizeof(struct node));
return (struct node*)p;
}
Edit:
and free it at the end! – Woodrow Barlow
The segmentation fault is because your code is pointing to NULL.
If you replace calls to init() with simple NULL (which is what it is), you will see for yourself that append tries to use NULL->next.
In append, you should check for 'temp!=NULL' first to avoid the seg fault. Also you are declaring an unnecesary local variable which you are not using at all.
I need to go through a list linked by the middle of a function with a parameter that is a triple pointer, by means of a recursive void function.
The program is as follows
typedef struct node
{
int data;
struct node* next;
}Node;
void insert(Node** first,int d){
Node* new= createNode(d);
new->next= *first;
*first=new;
}
Node* createNode(int d){
Node* new= (Node*)malloc(sizeof(Node));
new->data= d;
new->next=NULL;
return new;
}
void printList(Node***p)
{
Node**temp = *p;
if(temp == NULL)
return;
else
{
printf("\nValue: %d", (*temp)->data);
*temp = (*temp)->next;
printList(&temp);
}
}
int main()
{
Node *first = NULL;
int n =10;
while(n>0){
insert(&first,n);
n=n-1;
}
Nodo **ptr_first= &first;
printList(&ptr_first);
return 0;
}
The function prints all the values, but the program hangs and returns a negative value. What is wrong with this implementation?
PD: The use of the triple pointer is only for teaching purposes
Your recursion termination condition is wrong.
You have tho change if(temp == NULL) to if(*temp == NULL), since *temp is pointing to the element and not temp.
I also think that it is not good for teaching if you use triple pointers since they are not necessary here.
I try to implement a binary tree in C with only one operation for the moment - insertion of a node to the tree. The problem I am facing is that I have a segmentation fault. The problem comes from the function insert, in the root = leaf instruction but I can't figure out how can I fix it. I've tried to write the function in a slightly different way. Instead of passing a leaf, I tried to pass a value to the insert function and to create a node of the binary tree inside the insert function. It didn't work out.
Can you please me tell me where I am wrong in my code? Thank you
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct binaryTree
{
int data;
struct binaryTree *left;
struct binaryTree *right;
};
//the seg fault comes from the function insert
void insert(struct binaryTree *leaf,struct binaryTree *root)
{
if(root == NULL)
{
//this is the problematic instruction
root = leaf;//construct the tree if it has not been constructed before
root->left = NULL;
root->right = NULL;
}
else if(leaf->data > root->data)
{
insert(leaf, root->right);
}
else if(leaf->data < root->data)
insert(leaf,root->left);
else
{
printf("The element is in the tree already.\n");
}
}
void print(struct binaryTree *root)
{
printf("-------Print--------\n");
if(root == NULL) return;
print(root->left);
printf("%d\n", root->data);
print(root->right);
}
void createNode(int value,struct binaryTree *node)
{
printf("-------CreateNode--------\n");
node = malloc(sizeof(struct binaryTree));
node->data = value;
node->left = NULL;
node->right = NULL;
}
void destroy(struct binaryTree *root)
{
if(root != NULL)
{
destroy(root->right);
destroy(root->left);
free(root);
}
}
int main()
{
struct binaryTree *root = NULL,*a,*b,*c;
createNode(42,a);
createNode(13,b);
createNode(20,c);
insert(a,root);
insert(b,root);
insert(c,root);
print(root);
destroy(root);
return 0;
}
The problem:
At the beginning of main(), root is NULL and a is untitialised.
The problem is that createNode(42,a); will create and allocate a node, but it's address will be lost. Only the local parameter node will be set by this function and lost forever as soon as it returns. This value will not be copied to a, which hence remain unitialized.
Then you try to instert(a, root): a is still an unitialised pointer and root is still NULL. The first thing that will hapen in insert() is that you'll copy the unitialised pointer into root, and then you dereference this invalid pointer by trying to set some structure members to NULL. That causes the segmentation fault !
How to solve it:
Make sure that createNode() returns the value:
struct binaryTree *createNode(int value)
{
printf("-------CreateNode--------\n");
struct binaryTree *node = malloc(sizeof(struct binaryTree));
node->data = value;
node->left = NULL;
node->right = NULL;
return node;
}
and change min accordingly:
a = createNode (42);
...
You then have a similar problem in insert(), with the root argument. You could here do a similar technique, by rewriting your function:
struct binaryTree *insert(struct binaryTree *leaf,struct binaryTree *root) {...}
But it requries a little bit more gynmnastics as with createNode().
I propose you therefore another alternative, passing as argument a pointer to a root pointer: this pemits you to change the value of the root poniter
void insert(struct binaryTree *leaf,struct binaryTree **root) // pointer to pointer
{
if(*root == NULL)
{
//this is the problematic instruction
*root = leaf;//construct the tree if it has not been constructed before
(*root)->left = NULL;
(*root)->right = NULL;
}
else if(leaf->data > (*root)->data)
{
insert(leaf, &root->right);
}
else if(leaf->data < (*root)->data)
insert(leaf,&root->left);
else
{
printf("The element is in the tree already.\n");
}
}
In main you'd then call it:
insert(a,&root);
I am trying to make a BST from a given array and then traverse it In-Order. There are no compilation errors but at run time the error is Segmentation fault (core dumped). I have been unable to figure out the cause of the error(tried to browse stackoverflow for similar cases). The code is as follows:
#include<stdio.h>
#include<stdlib.h>
struct TreeNode{
int data;
struct TreeNode *right;
struct TreeNode *left;
};
struct TreeNode *newTreeNode(){
struct TreeNode *node = malloc(sizeof(struct TreeNode));
if(node){
node->data = 0;
node->left = NULL;
node->right = NULL;
return node;
}
else{
printf("Memory Error");
}
};
void InorderTraversalRecursive(struct TreeNode *node){
InorderTraversalRecursive(node->left);
printf("%d",node->data);
InorderTraversalRecursive(node->right);
}
struct TreeNode *InsertIntoTree(struct TreeNode *node, int data){
if(node == NULL){
node = newTreeNode();
node->data = data;
node->left = node->right = NULL;
}
else{
if(data > node->data)
InsertIntoTree(node->right, data);
else if(data < node->data)
InsertIntoTree(node->left, data);
}
return node;
}
struct TreeNode *MakeTreeFromData(int *arr){
int size = sizeof(arr)/sizeof(arr[0]);
struct TreeNode *root;
root = newTreeNode();
int i;
for(i=0;i<size;i++){
InsertIntoTree(root,arr[i]);
}
return root;
}
void main(){
int data[] = {4,2,6,1,7,3,5,8};
struct TreeNode *root;
root = MakeTreeFromData(data);
InorderTraversalRecursive(root);
}
One more error is in function InorderTraversalRecursive. The code should be:
void InorderTraversalRecursive(struct TreeNode *node)
{
if(!node)
return;
InorderTraversalRecursive(node->left);
printf("%d",node->data);
InorderTraversalRecursive(node->right);
}
This would eliminate the segmentation fault.
You should pass the size of array in function MakeTreeFromData().
So the declaration becomes
struct TreeNode *MakeTreeFromData(int *arr,int size)
where size is calculated by the same formula but inside main and then passed to the function.
Moreover, the function InsertIntoTree() should be defined as
struct TreeNode *InsertIntoTree(struct TreeNode *node, int data)
{
if(node==NULL)
{
node = newTreeNode();
node->data = data;
node->left = node->right = NULL;
}
else
{
if(data >= node->data)
node->right = InsertIntoTree(node->right, data);
else
node->left = InsertIntoTree(node->left, data);
}
return node;
}
And voila you get the correct output!!!
One obvious error is in this line
int size = sizeof(arr)/sizeof(arr[0]);
where arr is not an array but a pointer. This doesn't do at all what you think it is doing. You'd have to pass the size of your array as a parameter to your function.
If you have one powerful tool to know about when coding in C is GDB.
Read some tutorials and you won't need to ask this questions.
In my personal experience, I loved the gdb experience with emacs.
Hey i am starting to work on Huffman coding and I have a bit of a problem I getting this error
Segmentation fault (core dumped)
I understand it is caused by trying to reach memory you are not allow to but I can not realize what is the problem in my code, thank in advnace for the help!
src.txt - http://pastebin.com/kDf8nEhV
#include <stdio.h>
#include <stdlib.h>
int freq[256] = {0};
struct Node {
unsigned char m_ch;
int m_freq;
struct Node* m_ls, *m_rs;
struct Node* m_hls, *m_hrs;
};
struct Node* createNode(int freq, char ch);
void insertTree(struct Node** root, struct Node* n);
struct Node* getBinTree(FILE* fsrc);
void inorder(struct Node* root);
int main() {
FILE* fsrc;
struct Node* tree = (struct Node*)malloc(sizeof(struct Node));
fsrc = fopen("src.txt", "rb");
tree = getBinTree(fsrc);
inorder(tree);
return 1;
}
struct Node* createNode(int freq, char ch) {
struct Node* pNode = (struct Node*)malloc(sizeof(struct Node));
pNode->m_freq = freq;
pNode->m_ch = ch;
return pNode;
}
void insertTree(struct Node** root, struct Node* n) {
if (!(*root)) {
*root = n;
return;
}
if (n->m_freq < (*root)->m_freq) {
insertTree(&(*root)->m_ls, n);
} else {
insertTree(&(*root)->m_rs, n);
}
}
struct Node* getBinTree(FILE* fsrc) {
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
struct Node** root = (struct Node**)malloc(sizeof(struct Node*));
*root = (struct Node*)malloc(sizeof(struct Node));
int c, i;
while ((c = fgetc(fsrc)) != EOF) {
freq[c]++;
}
freq[255] = 1;
fclose(fsrc);
for (i = 0; i < 256; i++) {
if (freq[i] > 0) {
temp = createNode(freq[i], i);
insertTree(root, temp);
}
}
}
void inorder(struct Node* root) {
if (root != NULL) {
inorder(root->m_ls);
printf(" %d\n", root->m_freq);
inorder(root->m_rs);
}
return;
}
Your,
struct Node* getBinTree(FILE *fsrc)
is not returning anything.
You should enable compiler warnings, the compiler would have told you about that, the function is not returning a value, but you still assign it to tree in main().
But apart from that there is a serious problem with your code, a simple example
int main()
{
FILE *fsrc;
struct Node *tree = (struct Node*)malloc (sizeof(struct Node));
fsrc = fopen("src.txt","rb");
tree=getBinTree(fsrc);
inorder(tree);
return 1;
}
This single function has many problems,
You allocate new memory and point to it with tree, but you never use it because you overwrite the pointer here
tree = getBinTree(fsrc);
that causes a memory leak.
You don't check if the file was succesfuly opened, you must check
fsrc = fopen("src.txt", "rb");
if (fsrc == NULL)
return -1;
You don't need to cast malloc()
struct Node *tree = malloc(sizeof(*tree));
this is more robust, and easier to read.
You have to make sure that malloc() did not fail to allocate memory, when it does NULL is returned, so you need this when you do a malloc() that is actually required, for example in getBinTree()
struct Node *tree = malloc(sizeof(*tree));
if (tree == NULL)
return NULL;
i.e., copy malloc()'s behavior by returning NULL on failure.