Receive SIGSEGV in _IO_vfscanf_internal() - c

My program will compile and run normally, however, when I run the program through GDB, I receive a SIGSEGV, Segmentation fault
(0x0000003ec945352f in _IO_vfscanf_internal () from /lib64/libc.so.6)
after the fscanf in my code fills a node of a linked list. What causes the segmentation fault in GDB but not when I run my program?
(gdb) s
90 fscanf(fp,"%s %s %d %d", newNode->record_->first_name_, newNode->record_->last_name_, &newNode->record_->student_id_, &newNode->record_->student_age_);
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x0000003ec945352f in _IO_vfscanf_internal () from /lib64/libc.so.6
#include <stdio.h>
#include <stdlib.h>
struct student_record_node
{
struct student_record* record_;
struct student_record_node* next_;
};
struct student_record
{
int student_id_;
int student_age_;
char first_name_[21];
char last_name_[21];
};
void parseFile();
struct student_record_node* student_record_allocate();
void appendNode(struct student_record_node* head, struct student_record_node* newNode);
void printNode(struct student_record_node* node);
void student_record_node_deallocate(struct student_record_node* node);
void printNodeList(struct student_record_node* head);
void swap(struct student_record_node** node1, struct student_record_node** node2);
void sortByAge(struct student_record_node** recordsHead);
void sortById(struct student_record_node** recordsHead);
void freeNodeList(struct student_record_node* head);
void student_record_node_deallocate(struct student_record_node* node);
int main(int argc, char* argv[])
{
struct student_record_node* node = student_record_allocate();
struct student_record_node** head = &node;
parseFile(argv[1], head);
printf("Before sorting...\n");
printNodeList(*head);
sortByAge(head);
printf("Sorting by age...\n");
printNodeList(*head);
sortById(head);
printf("Sorting by id...\n");
printNodeList(*head);
freeNodeList(*head);
}
struct student_record_node* student_record_allocate()
{
struct student_record_node* newNode;
newNode = calloc(1, sizeof(struct student_record_node));
if (newNode == NULL)
{
printf("No memory allocated for newNode");
exit(1);
}
newNode->record_ = calloc(1, sizeof(struct student_record));
if (newNode->record_ == NULL)
{
printf("No memory allocated for record_");
exit(1);
}
newNode->next_ = NULL;
return newNode;
}
void parseFile(char* filename, struct student_record_node** head)
{
int i = 0;
struct student_record_node* newNode = *head;
FILE* fp;
fp = fopen(filename,"r");
if (fp == NULL)
{
printf("Could not read file\n");
exit(1);
}
while(1)
{
if(newNode != *head)
{
newNode = student_record_allocate();
appendNode(*head, newNode);
}
fscanf(fp,"%s %s %d %d", newNode->record_->first_name_, newNode->record_->last_name_, &newNode->record_->student_id_, &newNode->record_->student_age_);
if(newNode == *head)
{
newNode = NULL;
}
if(feof(fp))
{
break;
}
}
fclose(fp);
}
void appendNode(struct student_record_node* head, struct student_record_node* newNode)
{
int i = 1;
struct student_record_node* current = head;
while (i)
{
if (current->next_ == NULL)
{
current->next_ = newNode;
i = 0;
}
current = current->next_;
}
}
void printNode(struct student_record_node* node)
{
printf("struct student_record_node:\n");
printf("\tStudent first name: %s\n", node->record_->first_name_);
printf("\tStudent last name: %s\n", node->record_->last_name_);
printf("\tStudent id: %d\n", node->record_->student_id_);
printf("\tStudent age: %d\n", node->record_->student_age_);
}
void printNodeList(struct student_record_node* head)
{
struct student_record_node* current = head;
while (current->next_ != NULL)
{
printNode(current);
current = current->next_;
}
printf("\n");
}
void swap(struct student_record_node** node1, struct student_record_node** node2)
{
struct student_record* newNode;
struct student_record_node* big = *node2;
struct student_record_node* small = *node1;
newNode = big->record_;
big->record_ = small->record_;
small->record_ = newNode;
}
void sortByAge(struct student_record_node** recordsHead)
{
int i,j;
struct student_record_node* current = *recordsHead;
struct student_record_node* next = *recordsHead;
while (current->next_->next_ != NULL)
{
next = current;
while (next->next_->next_ != NULL)
{
if (next->next_->record_->student_age_ <= next->record_->student_age_)
{
swap(&next->next_, &next );
}
next = next->next_;
}
current = current->next_;
}
}
void sortById(struct student_record_node** recordsHead)
{
int i = 0;
struct student_record_node* current = *recordsHead;
struct student_record_node* beginning = *recordsHead;
struct student_record_node* next = *recordsHead;
while (current->next_->next_ != NULL)
{
next = beginning;
while(next->next_->next_ !=NULL)
{
if (next->next_->record_->student_id_ <= next->record_->student_id_)
{
swap(&next->next_, &next);
}
next = next->next_;
}
current = current->next_;
}
}
void student_record_node_deallocate(struct student_record_node* node)
{
struct student_record_node* tmp;
tmp = node;
free(tmp->record_);
free(tmp);
}
void freeNodeList(struct student_record_node* head)
{
while (head != NULL)
{
student_record_node_deallocate(head);
head = head->next_;
}
}

Related

I am trying to reverse a linked list using recursion in C, I have some doubts on my recursive function

Below is the program
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
struct node* reverse_ll(struct node* hnode)
{
if(hnode == 0)
{
return 0;
}
if(hnode->next == 0)
{
head=hnode;
return hnode;
}
struct node* ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next=0;
//return hnode;
}
void display()
{
struct node *ptr;
ptr=head;
if(ptr==0)
{
printf("empty");
}
else
{
while(ptr!=0)
{
printf("%d->",ptr->data);
ptr=ptr->next;
}
printf("null");
}
}
int main()
{
struct node* h;
lastinsert(1);
lastinsert(2);
lastinsert(3);
lastinsert(4);
lastinsert(5);
display();
h=reverse_ll(head);
display();
return 0;
}
In function reverse_ll() even if I comment "return hnode" I am getting the right output How is it possible where does ptr receives its address from when I comment "return hnode"?
output: 1->2->3->4->5->null
5->4->3->2->1->null
reverse_ll() must return a struct node * in the recursive case:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head;
void lastinsert(int data) {
struct node **c = &head;
for(; *c; c = &(*c)->next);
*c = malloc(sizeof(*head));
if (!(*c)) {
printf("malloc failed\n");
return;
}
(*c)->data = data;
(*c)->next = NULL;
}
struct node *reverse_ll(struct node* hnode) {
if(!hnode)
return NULL;
if(!hnode->next) {
head = hnode;
return hnode;
}
struct node *ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next = NULL;
return hnode;
}
void display() {
if(!head) {
printf("empty");
return;
}
for(struct node *ptr = head; ptr; ptr = ptr->next) {
printf("%d->",ptr->data);
}
printf("null\n");
}
int main() {
for(int i = 1; i <= 5; i++) {
lastinsert(i);
}
display();
reverse_ll(head);
display();
// It's good practice to implement a function that frees you list
// which you would call here.
return 0;
}
and example run:
$ ./a.out
1->2->3->4->5->null
5->4->3->2->1->null

Add to linked list via tail pointer without 3 levels of indirection

I am working on a project that requires an implementation of a linked list. Before I started the project, I was reviewing the classic method of creating a linked list.
I realized that in the past, I had been adding elements to a linked list via the head pointer that traverses the list until it reaches the null pointer.
I figured out that there is no need to do it this way, and to implement it in a way that involves a tail pointer, but the only way I could think of is a one that involves a triple pointer or a global pointer. I was wondering, is there an easier approach that uses less levels of indirection?
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
int val;
struct list *next;
} list;
void printlist(list *head);
void freelist(list *head);
void AddList(list ***tail, int val);
int main(void)
{
/* create first node */
list *head = (list *)malloc(sizeof(*head));
/* assign members of first node */
head->val = 1;
head->next = NULL;
/* create tail */
list **tail = &head->next;
/* add values to list */
AddList(&tail, 2);
AddList(&tail, 3);
AddList(&tail, 4);
AddList(&tail, 5);
AddList(&tail, 6);
AddList(&tail, 7);
AddList(&tail, 8);
AddList(&tail, 9);
/* print list */
printlist(head);
/* free list */
freelist(head);
/* exit program */
system("pause");
return 0;
}
void AddList(list ***tail, int val)
{
list *node = (list *)malloc(sizeof(*node));
node->val = val;
node->next = NULL;
**tail = node;
*tail = &node->next;
}
void printlist(list *head)
{
while (head) {
printf("%d\n", head->val);
head = head->next;
}
}
void freelist(list *head)
{
list *tmp = head;
while (head) {
head = head->next;
free(tmp);
tmp = head;
}
}
The tail pointer should point to the last node, not the next pointer of the last node:
In main:
/* create tail */
list *tail = head;
In AddList:
void AddList(list **tail, int val)
{
list *node = malloc(sizeof(*node));
node->val = val;
node->next = NULL;
(*tail)->next = node;
*tail = node;
}
You can do:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node NODE;
struct llist {
unsigned int count;
NODE *head;
NODE *tail;
};
typedef struct llist LLIST;
LLIST *create_list() {
LLIST *llist = malloc(sizeof(LLIST));
if (llist == NULL)
exit(EXIT_FAILURE);
llist->head = NULL;
llist->tail = NULL;
llist->count = 0;
return llist;
}
NODE *create_ll_node(int data) {
NODE *node = malloc(sizeof(NODE));
if (node == NULL)
exit(EXIT_FAILURE);
node->data = data;
node->next = NULL;
return node;
}
void add_list_head(LLIST *llist, int data) {
NODE *node = create_ll_node(data);
if (llist->head == NULL) {
llist->head = node;
llist->tail = node;
} else {
node->next = llist->head;
llist->head = node;
}
llist->count++;
}
void add_list_tail(LLIST *llist, int data) {
NODE *node = create_ll_node(data);
if (llist->tail == NULL) {
llist->head = node;
llist->tail = node;
} else {
llist->tail->next = node;
llist->tail = node;
}
llist->count++;
}
void delete_list_elements(NODE *llist_head) {
NODE *node, *tmp;
if (llist_head == NULL) {
printf ("List is empty.\n");
return;
}
node = llist_head;
while(node) {
tmp = node->next;
free(node);
node = tmp;
}
}
void delete_list(LLIST *llist) {
if (llist == NULL) {
printf ("Invalid list.\n");
return;
}
delete_list_elements(llist->head);
free(llist);
}
void display_list(const LLIST *llist) {
if (llist == NULL) {
printf ("Invalid list.\n");
return;
}
if (llist->head == NULL) {
printf ("List is empty.\n");
return;
}
NODE *node = llist->head;
while(node) {
printf ("data: %d\n", node->data);
node = node->next;
}
}
unsigned int get_list_element_count(const LLIST *llist) {
if (llist == NULL)
return 0;
return llist->count;
}
int main() {
LLIST *llist = create_list();
add_list_head(llist, 5);
add_list_head(llist, 4);
add_list_head(llist, 3);
add_list_head(llist, 2);
add_list_head(llist, 1);
add_list_tail(llist, 6);
add_list_tail(llist, 7);
add_list_tail(llist, 8);
add_list_tail(llist, 9);
add_list_tail(llist, 10);
display_list(llist);
printf ("Total elements in list : %u\n", get_list_element_count(llist));
delete_list(llist);
return 0;
}

Code to insert node at last position in C programming language

I am writing a code on linklist in C programming language. When I am using an online compiler my code is working fine but when I am using Codeblock to run the code, the code is not working. I am posting the code kindly provide me solution. My code is to add node in a linklist on the last position.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* Head;
void insert(int);
void print();
int main()
{
Head = NULL;
insert(2);
insert(3);
insert(4);
print();
return 0;
}
void insert(int a)
{
struct Node* temp1=(struct Node*)malloc(sizeof(struct Node));
temp1-> data = a;
temp1-> next = NULL;
if(Head == NULL)
{
Head = temp1;
return;
}
struct Node* temp = Head;
while(temp->next!= NULL)
{
temp = temp->next;
}
temp-> next = temp1;
}
void print()
{
struct Node* temp2=Head;
while(temp2 != NULL)
{
printf("%d \n", temp2->data);
temp2 = temp2->next;
}
return;
}
Here is how you can achieve what you want to do.
I suggest you to use a top-down approach when programming.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *next;
};
struct node *Insert(struct node *, int);
void Print_List(struct node *);
void Remove_List(struct node *);
int main(int argc, char **argv)
{
struct node *head;
head = NULL;
head = Insert(head, 10);
head = Insert(head, 20);
Print_List(head);
Remove_List(head);
head = NULL;
return 0;
}
struct node *Create_New_Node(int);
struct node *Head_Insert(struct node *, int);
struct node *Queue_Insert(struct node *, int);
struct node *Insert(struct node *, int);
void Print_List(struct node *);
void Remove_List(struct node *);
struct node *Insert(struct node *top, int elem)
{
if(top == NULL)
{
top = Head_Insert(top, elem);
}
else
{
top = Queue_Insert(top, elem);
}
return top;
}
struct node *Create_New_Node(int elem)
{
struct node *new_node;
new_node = (struct node *)malloc(sizeof(struct node));
if(new_node != NULL)
{
new_node -> info = elem;
new_node -> next = NULL;
}
return new_node;
}
struct node *Head_Insert(struct node *top, int elem)
{
struct node *new_node = Create_New_Node(elem);
if(new_node != NULL)
{
new_node -> next = top;
}
return new_node;
}
struct node *Queue_Insert(struct node *top, int elem)
{
if(top != NULL)
{
if(top -> next != NULL)
{
top -> next = Queue_Insert(top -> next, elem);
}
else
{
struct node *new_node = Create_New_Node(elem);
if(new_node != NULL)
{
top -> next = new_node;
}
}
}
return top;
}
void Print_List(struct node *top)
{
while(top != NULL)
{
printf("\nInfo : %d\tAddress : %u\tNext link address : %u\n", top -> info, top, top -> next);
top = top -> next;
}
return;
}
void Remove_List(struct node *top)
{
if(top != NULL)
{
Remove_List(top -> next);
top -> next = NULL;
free(top);
}
return;
}
Sample output :
Info : 10 Address : 39149584 Next link address : 39149616
Info : 20 Address : 39149616 Next link address : 0

segmenation fault error in my linkedList -C

I put together a few pieces of code to make a linked list that adds to head(Has a special function) and in the middle(also special function).
my problem is, i need to provide the program with numbers and insert them as nodes in my LINKEDLIST. However, my display function(to display the tree of nodes) gives back segmentation fault and so does just taking values in without any display function.
I'm fairly new to malloc so i suspect the problem is there?
Thanks
#include<stdio.h>
#include<stdlib.h>
/*LINKEDLIST STRUCT*/
struct node {
int data;
struct node *next;
};
/*Inserting head-Node*/
struct node *insert_head(struct node *head, int number)
{
struct node *temp;
temp = malloc(sizeof(struct node));
if(temp == NULL)
{
printf("Not enough memory\n");
exit(1);
}
temp->data = number;
temp->next = head;
head = temp;
return head;
}
/*Inserting inside a list*/
void after_me(struct node *me, int number)
{
struct node *temp;
temp = malloc(sizeof(struct node));
if(temp == NULL)
{
printf("Not enough memory\n");
exit(1);
}
temp->data = number;
temp->next = me->next;
me->next = temp;
}
/*PRINTING LIST*/
void display(struct node *head)
{
struct node *moving_ptr = head;
while(moving_ptr != NULL)
{
printf("%d-->",moving_ptr->data);
moving_ptr = moving_ptr->next;
}
}
int main()
{
int index;
struct node *head;
struct node *previous_node;
scanf("%d", &index);
while(index > 0)
{
/*allocating in List */
if(head == NULL)
head = insert_head(head,index);
else
if((head != NULL) && (index <= (head->data)))
{
struct node *temp;
head->next = temp;
temp->next = head;/*TRY INSERT HEAD FUNC.*/
}
else
if((head != NULL) && (index > (head->data)))
{
previous_node->data = index-1;
after_me(previous_node,index);
}
scanf("%d", &index);
}
display(head);
}
I suggest as follows.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
//aggregated into one place
struct node *new_node(int number){
struct node *temp;
if(NULL == (temp = malloc(sizeof(*temp)))){
printf("\nNot enough memory\n");
exit(1);
}
temp->data = number;
temp->next = NULL;
return temp;
}
struct node *insert_head(struct node *head, int number) {
struct node *temp = new_node(number);
temp->next = head;
return temp;
}
void after_me(struct node *me, int number){
struct node *temp = new_node(number);
temp->next = me->next;
me->next = temp;
}
void display(struct node *head){
struct node *moving_ptr = head;
while(moving_ptr != NULL){
printf("%d", moving_ptr->data);
if(moving_ptr = moving_ptr->next)
printf("-->");
}
putchar('\n');
}
struct node *insert(struct node *me, int number){
if(me){
if(number <= me->data){
me = insert_head(me, number);
} else {
me->next = insert(me->next, number);
}
} else {
me = new_node(number);
}
return me;
}
void release(struct node *list){//Of course, you will be able to replace a simple loop(e.g while-loop).
if(list){
release(list->next);
free(list);
}
}
int main(void){
struct node *head = NULL;
int index;
while(1==scanf("%d", &index) && index > 0){
head = insert(head, index);
}
display(head);
release(head);
return 0;
}

Nested singly linked list

This function which is supposed to add items to clients isn't working for me. The rest seems to be working properly.
#include <stdio.h>
#include <stdlib.h>
struct item{
char item_name[30];
struct item *NextItem;
};
struct client{
struct client *NextClient;
char name[30];
char last_name[30];
struct item *firstItem;
struct item *lastItem;
};
struct client *head = NULL;
/////////////////////////////
struct client* FindTailClient(struct client* head)
{
struct client *temp = head;
while( temp->NextClient != NULL)
{
temp = temp->NextClient;
}
return temp;
}
/////////////////////////////
////////
struct client *GetClientData()
{
char data[30];
struct client *temp;
temp = (struct client*)malloc(sizeof(struct client));
printf("Enter the person's name--->");
scanf("%s",data);
strcpy(temp->name,data);
printf("Enter the person's last name--->");
scanf("%s",data);
strcpy(temp->last_name,data);
temp->NextClient = NULL;
return temp;
}
///////////
struct item *GetItemData()
{
struct item *temp;
char data[30];
temp = (struct item*)malloc(sizeof(struct item));
printf("Enter the item name--->");
scanf("%s",data);
strcpy(temp->item_name,data);
temp->NextItem = NULL;
return temp;
}
///////////
//////////////
struct client* AddClient()
{
struct client *temp,temp1;
temp=head;
struct client *data = GetClientData();
if(head == NULL)
{
head=data;
head->NextClient = NULL;
}
else
{
while(temp->NextClient != NULL)
{
temp=temp->NextClient;
}
data->NextClient=NULL;
temp->NextClient=data;
}
}
///////////////////
void display()
{
struct client *temp=head;
if(temp==NULL)
{
printf("\nList is Empty");
}
else
{
printf("\nElements in the List: ");
while(temp!=NULL)
{
printf(" -> %s ->%s ",temp->name,temp->last_name);
temp=temp->NextClient;
}
printf("\n");
}
}
///////////////////
void AddItemToClient(struct client* head, struct item *item)
{
item->NextItem = NULL;
if(head->firstItem == NULL) {
head->firstItem = item;
} else {
head->firstItem->NextItem = item;
}
head->lastItem = item;
}
///////////////////
struct client *find(struct client *head, char name[])
{
while (head->NextClient != NULL )
{
if (strcmp(head->name,name) == 0)
{
printf("Target found: %s\n",head->name);
return head;
}
head = head->NextClient;
}
printf("target not found");
return NULL;
}
//////////////////
int main()
{
int i;
char data[30];
char name[30];
struct client *temp;
struct client *head;
struct item *data1;
for(i=0;i<2;i++)
{
AddClient();
}
display();
printf("Insert name to find:");
scanf("%s",name);
temp = find(&head,name);
data1 = GetItemData();
AddItemToClient(temp,&data1);
display();
}
This is wrong
void AddItemToClient(struct client* head, struct item *item)
{
item->NextItem = NULL;
if(head->firstItem == NULL) {
head->firstItem = item;
} else {
head->firstItem->NextItem = item;
}
head->lastItem = item;
}
Should be
void AddItemToClient(struct client* head, struct item *item)
{
item->NextItem = NULL;
if(head->firstItem == NULL) {
head->firstItem = item;
} else {
head->lastItem->NextItem = item;
}
head->lastItem = item;
}

Resources