Segment Fault when initialization multiple nodes - c

I am working on a binary search tree in C. I am having a problem with initializing multiple nodes.
typedef struct Node Node;
struct Node{
int* data;
Node* leftChild;
Node* rightChild;
Node* parent;
};
void initNode(Node* node, int* data){
node->data = data;
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
The above code seems to work fine when calling initNode() only once. But if I attempt to make the second call I get a segment fault.
My main looks like this:
int main(){
Node* node;
Node* node2;
int a = 12;
int b = 15;
initNode(node, &a);
printf("%i \n", *node->data);
}
This works. However if I do this:
int main(){
Node* node;
Node* node2;
int a = 12;
int b = 15;
initNode(node, &a);
initNode(node2, &b);
printf("%i \n", *node->data);
}
I get a segment fault. Any ideas why this behavior is happening?

You have not allocated memory for both node or node2. Since both the pointers are allocated on stack they will have junk values. Its just accident that the first program passes at all.

This function:
void initNode(Node* node, int* data){
node->data = data;
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
expects node to have already been initialized.
You don't do that in either of your programs. Dereferencing a pointer that hasn't been assigned is undefined behavior. It's just by chance that it worked in your first program. Who knows what memory you're overwriting.
You need to initialize node and node2.
Node* node = malloc(sizeof*node);
Node* node2 = malloc(sizeof*node2);
Just remember to free them once you're finished with them.
A much cleaner solution is to allocate the Nodes on the stack, so you don't have to worry about calling free.
int main(void) { /* use a valid signature for main() */
Node node; /* just a straight up Node (not a pointer) */
Node node2;
int a = 12;
int b = 15;
initNode(&node, &a); /* use address of operator on nodes */
initNode(&node2, &b);
printf("%i \n", *node->data);
}

Related

Printing doubly linked list in C goes into infinite loop

Im trying to learn doubly linked lists. I used the following to print:
typedef struct Node{
int data;
struct Node* prev;
struct Node* next;
}node;
typedef struct List{
node *head;
}list;
node * createNode(int data) {
node * newNode = (node*)malloc(sizeof(node));
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
_Bool isEmpty(const list *L)
{
if (L->head == NULL)
return 1;
return 0;
}
_Bool insert(list *L, node *N) {
if(isEmpty(L)) {
L->head = N;
}
else{
L->head->prev = N;
N->next = L->head;
L->head = N;
}
if (L->head==N)
return 1;
return 0;
}
void _print(list *L){
node *temp=L->head;
while(temp!=NULL){
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(int argc, char *argv[]){
list *L1=(list *)malloc(sizeof(list));
node *N1=createNode(3);
node *N2=createNode(1);
node *N3=createNode(5);
insert(L1, N3);
insert(L1, N2);
insert(L1, N1);
_print(L1);
}
for reference my list struct only contains a pointer "head" and my node struct contains next, prev and data.
It prints the correct data but goes into infinite loop.
What is the reason ?
The problem is that this line in main:
list *L1=(list *)malloc(sizeof(list));
Allocates memory for the list, but does not initialize it.
Without initialization the value of L1->head can be anything.
And if it happens to be different than 0 (i.e. NULL), insert will interpret it as pointing to a valid node (which it isn't).
The result is undefined behavior (UB), which means anything can happen. It might seem to work, it can crash, or get into an infinite loop etc.
In order to fix it, you need to initialize the list pointed by L1.
You can do it at least in 2 ways:
Replace the call to malloc with calloc, which also zeroes the allocated memory:
list* L1 = (list*)calloc(sizeof(list), 1);
Add an explicit initialization after the malloc:
list* L1 = (list*)malloc(sizeof(list));
L1->head = NULL; /* <--- initialization */
You can also add a function for encapsulating the initialization.

Simple Linked List in C. Segmentation Fault 11

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.

Assignment between pointers work only inside main, not in procedure body

I'm getting a segmentation fault error, if I try to make a copy between pointers to a struct, inside a procedure body.
If I instead, make the copy between pointers within the main() body, everything works correctly.
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *father, *lchild, *rchild;
} node;
typedef struct node Node;
// Prototypes
Node* insertRoot(int val, Node* N);
int main(){
Node * A = NULL;
Node * b = insertRoot(10, A);
//A = b; // If I do the assignment here it works correctly.
printf("A->value = %d \n\n" , A->value); //Segmentation fault!
return 0;
}
Node* insertRoot(int val, Node* N){
Node* temp = malloc(sizeof(Node));
temp->value = val;
temp->father = NULL;
temp->lchild = NULL;
temp->rchild = NULL;
N = temp; // If I do the assignment here instead, it won't work.
return temp;
};
You are not assigning any value to A inside insertRoot, you are assigning to N which is a copy of A. That leaves the value A=NULL unchanged.

Segmentation fault while trying to insert node into a linked list

I started learning C programming a few days ago through the book, Programming in C, and I have prior knowledge of java. Inserting a node into a linked list is very easy in java, but I thought if I could do the same in C.
So, I came up with this program,
#include "node.h"
void insertEntry(struct node* root, struct node* after)
{
struct node* first = root;
while(first != (struct node*) 0)
{
if(first->value == after->value)
{
struct node ins;
ins.value = 3456;
ins.next = first->next;
first->next = &ins;
}
first = first->next;
}
}
int main(void)
{
struct node n1, n2, n3;
struct node* list_pointer = &n1;
n1.value = 100;
n1.next = &n2;
n2.value = 200;
n2.next = &n3;
n3.value = 300;
n3.next = (struct node*) 0;
void insertEntry(struct node* root, struct node* after);
while (list_pointer != (struct node*) 0)
{
printf("%i\n", list_pointer->value);
list_pointer = list_pointer->next;
}
printf("\n");
list_pointer = &n1;
insertEntry(list_pointer, &n2);
while (list_pointer != (struct node*) 0)
{
printf("%i\n", list_pointer->value);
list_pointer = list_pointer->next;
}
return 0;
}
node.h
#include <stdio.h>
struct node
{
int value;
struct node* next;
};
Basically, this program takes pointer to the first element of the linked list and the pointer to the element after which it is to be inserted, and inserts a new node after this node.
But when I run this, my program crashes and I cannot find where or why this error occurs.
I looked over to the code in java and tried to implement the same in C.
Thank you.
Here's your problem:
{
struct node ins; // You create an object in the stack
ins.value = 3456;
ins.next = first->next;
first->next = &ins; // You reference your object
} // Your object is popped out of the stack and ceases to exist
// Any access to first->next past this block may cause segfault
In order to avoid this, you could create ins with malloc(), but beware: this isn't java and you have to keep track of all objects you allocated in the heap yourself.
The main problem is you insert a node that is allocated on the stack -- it's invalid as soon as the function is left. To allocate new memory, you need malloc() (don't forget to free() when done, there is no garbage collection).
A few side notes:
It's utterly pointless to cast 0 when used as a pointer to any specific pointer type ... 0 is 0.
You don't need the root node for inserting, so why pass it in the first place?
declaring a prototype inside of a function (in that case: main) doesn't make too much sense ... it will work without because the function you want to call is already defined in the same file.
#include headers where they are needed! node.h doesn't need stdio, the main program does.
A version of roughly your program that would work:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node
{
int value;
struct node *next;
};
struct node *insertEntry(struct node* after, int val)
{
assert(after); /* not NULL */
struct node *new = malloc(sizeof(struct node));
new->value = val;
new->next = after->next;
after->next = new;
return new;
}
void freeNodeList(struct node* root)
{
struct node *current, *last;
current = root;
while (current)
{
last = current;
current = current->next;
free(last);
}
}
int main(void)
{
struct node *n1, *n2, *n3;
struct node *ptr;
n1 = malloc(sizeof(struct node));
n2 = malloc(sizeof(struct node));
n3 = malloc(sizeof(struct node));
n1->value = 100;
n1->next = n2;
n2->value = 200;
n2->next = n3;
n3->value = 300;
n3->next = 0;
insertEntry(n2, 250);
ptr = n1;
while (ptr)
{
printf("%d\n", ptr->value);
ptr = ptr->next;
}
freeNodeList(n1);
return 0;
}
You should read up on gdb and how to use it.
gcc -Wall -O0 -g x.c -o x
x being your program to compile with debuging information and no optimisation.
then run your program through gdb to find the location/occurrence of the fault.
ie.
gdb x

Assign function to function field in C

I'm trying to assign a function to a variable field, but I get Segmentation fault.
Here is the code:
typedef struct node{
int info;
struct node *link;
void* (*make) (int x);
}node;
void* make_node(int x)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
return new_node;
}
int main(){
struct node *n;
n->make = make_node;
return 0;
}
What could be wrong?
you need to allocate some space to node on heap or just use a normal variable of the structure instead of a pointer.
Your n variable into main() is uninitialised.
The make_node() function will reserve space for a node structure, so why not call it inside main()?
You may try the code below.
typedef struct {
int info;
struct node *link;
void* (*make) (int x);
} node;
void *make_node(int x)
{
node* new_node = malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
return new_node;
}
int main() {
struct node *n;
n = make_node(1);
free (n);
return 0;
}
p.s avoid casting malloc returns
p.s.2 pay attention for the same problem when you'll use struct node *link inside node
p.s.3 remember to free() unused malloc()ed variables.
You have forgotten to assign a value to n.
Change the return type of make_node to node*
Do n=make_node(x)
And I strongly advise reading http://www.amazon.com/gp/aw/d/0131103628/ref=redir_mdp_mobile
This would be the best thing you can do now.
With the existing infrastructure, you could write:
typedef struct node
{
int info;
struct node *link;
void *(*make)(int x);
} node;
void *make_node(int x)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
new_node->make = make_node;
return new_node;
}
int main(void)
{
struct node *n = make_node(1);
...use the newly allocated node...
return 0;
}
This allocates the node before you try to write to it. It also fully initializes the node by setting every field to a known value. If you need a different function pointer for the make member, you can adjust afterwards.
You can allocate space for n on the stack this way:
int main() {
struct node n;
n.make = make_node;
return 0;
}
Otherwise you'd have to allocate it on the heap perhaps as a global variable or using malloc().

Resources