Segmentation fault in program using linked list - c

Code:
#include<stdio.h>
#include<malloc.h>
struct details{
char *name;
int no;
struct details *info;
};
//ADDING THE LINKED LIST
void add(struct details **info,int no,char * name){
struct details *temp=malloc(sizeof(struct details));
temp = *info;
if(temp == NULL){
temp = malloc(sizeof(struct details));
}
else{
if(temp->info == NULL){
temp->info = malloc(sizeof(struct details));
temp = temp->info;
}
}
temp->no = no;
temp->name = name;
}
//DISPLAYING THE LINKED LIST
void display(struct details *info){
while(info!=NULL){
printf("\nThe List is:\n","\n no: \tname:\n","%d","%s and link:%d",info->no,info->name,info->info);
info = info->info;
}
}
//MAIN PROGRAM
int main()
{
struct details* ptr;
char *name,ch;
int no;
int select_option;
ptr = NULL;
printf("\n ***MAIN MENU*** \n1.Add Element \n2.Delete Element \n3.Search Element \n4.Linked List Concatenation \n5.Invert Linked List \n6.Diplay Elements \n Please Enter your choice:(eg:1,2,3,4,5,6)\n");
scanf("%d",&select_option);
do{
switch(select_option){
case 1:
printf("Enter no to add:");
scanf("%d",&no);
printf("Enter name to add:");
scanf("%s",name);
add(&ptr,no,name);
break;
case 6:
display(ptr);
break;
default:
printf("INVALID CHOICE!");
break;
}
printf("Do u wish to continue?(y/n):");
scanf("%c",&ch);
}while(ch == 'y' || ch == 'y');
return 0;
}
I'm trying to write a simple program using a linked list to add and display data. But its throwing me a segmentation fault. I hope that I have initialized all the pointers with the memory. All help appreciated.

This:
temp->name = name;
does not copy name to temp->name but assigns temp->name to the same address as name, which is local to the function. You need to malloc() and strcpy():
temp->name = malloc(strlen(name) + 1);
strcpy(temp->name, name);
Remember to free(temp->name); when no longer required.
Additionally (as pointed out by Luchian), when reading from stdin:
char *name;
...
scanf("%s",name);
name has no memory allocated to. Declare it as an array but you need to protect against writing beyond the end of it:
char name[128];
...
scanf("%127s",name);

You haven't:
char *name;
///....
scanf("%s",name);
You never allocated memory for name.
You could do char name[50]; or whatever, but beware of overflows. Guard against them.

Both hmjd and Luchian Grigore answers are a prior problems, but also:
You don't initialize temp->info at any point after a malloc, so it is never NULL, but yet temp->info is an invalid address.
Either initialize it explicitly or use calloc, which initializes the allocated buffer, instead of malloc.

You forgot to allocate name
char *name

Related

In which one of the following two codes does memory leak occur? My professor says that its A, but I do not get it

My question here is that according to my professor, while in Program A, get_Name() causes memory leak, it doesn't cause any in Program B. I do not get why this is the case!
From what I can gather, there should be memory leak happening at get_Name() becuase malloc() is used. What I don't get is why case A? Any answers will be appreciated.
PROGRAM A:
struct actor {
char name[32];
struct actor *next;
} *head = NULL;
char *get_name()
{ char *q;
q = (char *) malloc(32);
printf("Please enter a name: ");
scanf("%s", q); return q;
};
int insertion()
{struct actor *c; char *n;
c = malloc(sizeof(struct actor));
if (c == 0) {
printf("out of memory\n"); return -1;}
n = get_name();
strcpy(c->name, n);
c->next = head;
head = c;
return 1
};
PROGRAM B:
struct actor {
char *name;
struct actor *next;
} *head = NULL;
char *get_name()
{ char *q;
q = (char *) malloc(32);
printf("Please enter a name: ");
scanf("%s", q); return q;
};
int insertion()
{struct actor *c; char *n;
c = malloc(sizeof(struct actor));
if (c == 0) {
printf("out of memory\n"); return -1;}
c->name = get_name();
c->next = head;
head = c;
return 1
};
The insertion() method from sample A string-copies the result of get_name() into a new string whereas the insertion in sample B copies the obtained pointer into a list that starts at head.
Somewhere lateron in the program, there must be a place where the complete list or its elements are deallocated by calling free(). This is not possible in sample A as the pointer to the string allocated with malloc() got lost after leaving insertion().

Ask data from user and store them inside a struct in C

In the code below I tried to use printf and scanf to get data from user and store them inside a struct i defined called node.
The programme works fine for the first prompt, but as soon as the user input name, the programme ends with printing Age:salary:
Can anyone help me with this?
On a side note, can anyone also help me to understand how to create a loop to store data in various nodes and store them together? (Not hard-code it one by one)
Thank you very much!!
typedef struct node
{
char *name;
int age;
int salary;
struct node * next;
}node;
int main(void)
{
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = NULL;
free(tmp);
}
Use a char[] for name,
for example:
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
char name[128];
int age;
int salary;
struct node * next;
}node;
int main(void)
{
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = NULL;
free(tmp);
}
If you want to get several users, loop for ever and ask if the user wants to add more data.
I have create a function to print the list
Console:
Name:Foo
Age:12
salary:12
Continue Y/N
Y
Name:Bar
Age:14
salary:14
Continue Y/N
Y
Name:John
Age:30
salary:45
Continue Y/N
N
John, 30, 45
Bar, 14, 14
Foo, 12, 12
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
char name[128];
int age;
int salary;
struct node * next;
}node;
static void printList(node *n)
{
while (n) {
printf("%s, %d, %d\n", n->name, n->age, n->salary);
n = n->next;
}
}
static node *get_nodes(void) {
node *list = NULL;
while (42) {
char c;
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = list;
list = tmp;
printf("Continue Y/N\n");
scanf(" %c", &c);
if (c == 'N')
break;
}
return list;
}
static void clearList(node *node) {
if (node->next) {
clearList(node->next);
}
free(node);
}
int main(void)
{
node *list = get_nodes();
printList(list);
clearList(list);
return 0;
}
You are trying to write to Uninitialized memory
This is a very common problem beginners face.
You are trying to store the name using char *name declaration.
Here name does not point to a valid memory location, that's why You program is not running as expected.
Even if name points to a valid memory address, you must have enough memory allocated to store the data.
You can use
#define BUFFER_SIZE 50
char name[BUFFER_SIZE];
You can use any buffer size as you like, and then store a string of that length - 1 in the name array. -1 is for the null termination character \0.
Using this declaration you are allocating memory of BUFFER_SIZE bytes and the name points to the first byte in that array.
This allocation happens on the stack not in the HEAP
For fix your bug, you should allocate memory of your char *.
First Way, when you create your struct.
typedef struct node
{
char name[200]; // You specify that your char * can save 200 char
int age;
int salary;
struct node * next;
}node;
or you can create init struct function
node *init_node()
{
node *test = null;
test->name = malloc(sizeof(char) * 200);
test->age = 0;
test->salary = 0;
test->node = null;
return test
}

Linked List in Hash Table (with struct)

I'm implementing a hash table with pointers to struct instances.
Struct:
typedef struct student
{
int matrikelnummer;
char *name;
struct student *next;
} student;
Array (with pointers on my struct):
student *hash_table[SIZE];
...
for (int i = 0; i < SIZE; i++)
hash_table[i] = NULL;
I'm creating a instance of my struct with proper memory management:
char *name = malloc(100);
student *temp = malloc(sizeof(student));
if (temp == NULL || name == NULL)
return;
printf("Neuer Student hinzufuegen:\n");
printf("Name: ");
scanf("%99s", name);
temp->name = malloc(strlen(name) + 1);
if (temp->name == NULL)
return;
strcpy(temp->name, name);
free(name);
name = NULL;
printf("Matrikelnumer: ");
scanf("%d", &temp->matrikelnummer);
temp->next = NULL;
Until here it is working properly, if I check my temp (instance of struct) while debugging the program it looks fine.
At the end of this function changing the pointer in hash_table[0] to my temp instance seems to work:
hash_table[0] = &temp;
/* hash_table[get_hash_key(temp->matrikelnummer)] = &temp; */
My program crashes after I try to print the members of my hash_table afterwards like following:
printf("matrikelnumer: %d\n", hash_table[0]->matrikelnummer);
Output: matrikelnummer: 9741328
(it looks like the address itself printed with %d)
and it crashes after trying to print the name with following code line:
printf("name: %s\n", hash_table[0]->name);
Do I access the variables wrong?
I tried already several ways to access the members, but its mostly crashing or doing something I'm not able to follow.
Any hints and help appreciated, also when it comes to coding style etc.
Bug is on line:
hash_table[0] = &temp;
temp is pointer already, so you are assigning struct student** to struct student* array element, which causes all remaining errors.
Change to:
hash_table[0] = temp;

Linked List Appcrash

I was trying to do an example about linked list. First, I added the values to the variables and there was no problem. But when I tried to get values from user, the program crashed when entering midterm 2 grade. I tried other input functions but the result is same. Where is the problem?
#include <stdio.h>
struct student
{
char *name;
int m1,m2,final;
struct student* next;
};
main()
{
addStudent();
system("PAUSE");
}
addStudent()
{
struct student *node = NULL;
struct student *firstnode;
firstnode = (struct student *)malloc(sizeof(struct student));
node = firstnode;
printf("press 0 to exit \n");
while(1)
{
printf("Student name: ");
scanf("%s", node->name)
if(node->name == "0") break;
printf("Midterm 1: ");
scanf("%d", node->m1);
printf("Midterm 2: ");
scanf("%d", node->m2);
printf("Final: ");
scanf("%d", node->final);
node->next = (struct student *)malloc(sizeof(struct student));
node = node->next;
}
node->next = NULL;
node = firstnode;
while(node->next);
while(node->next != NULL)
{
printf("%s - ",node->name);
printf("%d ", node->m1);
printf("%d ", node->m2);
printf("%d ", node->final);
node = node->next;
}
system("PAUSE");
return 0;
}
Fix 1
Remove the line
while(node->next);
Reason: It will put you on an infinite loop in most cases and it is unnecessary.
Fix 2
Replace the loop
while(node->next != NULL) {
}
with
if (node->next != NULL) {
while (node->next->next != NULL) {
}
}
Reason: You are allocating one additional struct each time and keeping it empty for reading next time. So the Linked List will end before the next becomes NULL.
Fix 3
Replace following in struct
char *name;
with
char name[80];
Reason: Memory not being allocated.
Fix 4
Replace at all occurrences of scanf (except for name)
scanf("%d", node->m1);
with
scanf("%d", &node->m1);
Reason: scanf needs memory location of data to be read.
Good luck
Your code has multiple errors.
To start with, the first scanf("%s", node->name) is missing its terminating semicolon.
Next, your function signatures are sloppy. main() should be int main(void). addStudent() should be int addStudent(void). (Or, get rid of its return 0 and let it return void.) Since you don't pre-declare addStudent(), you should define it before main() so that main() can know about it.
The crash, though, is because you haven't allocated memory for node->name. You've allocated memory for a node, but that doesn't give you space to put the name.

How do I copy a value of array of strings to char array?

I am writing a program that will let user add or delete the car from inventory.Right now,
I am trying to get user to choose a car name instead of explicitly stating name and I created a struct CriteriaSelector in which array name companyList will store value of companies and when I let user choose car name it will copy a string from companyList at a particular index into the char array called carname which will then be copied into carname char array in the CarData object.
The thing is whenever I compile the below code, I get the error saying expected specifier qualifier list before 'companyList' at line 27 and I don't know what to do?
Can anybody help?
#include <stdio.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 20
typedef struct cardata{
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
int quantity;
}CarData;
struct node{
CarData data;
struct node *next;
struct node *prev;
}*start=NULL;
typedef struct criteriaselector{
const char *companyList[10];
companyList[0] = "Toyota"; <-- This is where error is happening!!(Line 27)
companyList[1] = "Honda";
companyList[2] = "Hyundai";
companyList[3] = "Nissan";
companyList[4] = "Mitsubishi";
companyList[5] = "Volksvagon";
companyList[6] = "Acura";
companyList[7] = "Ford";
companyList[8] = "Dodge"
companyList[9] = "GMC";
}CriteriaSelector;
void insert_first(){
struct node *ptr;
CriteriaSelector criteriaselector;
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
int carQuantity;
int ch;
printf("\nChoose your car");
printf("\n\n\n1.Toyota \n2.Honda \n3.Hyundai \n4.Nissan \n5. Mitsubishi \n6. Volksvagon \n7. Acura \n8. Ford \n9. Dodge \n10. GNC Exit\n");
scanf("%d", &ch);
strcpy(carname,criteriaselector.companyList[ch-1]);
printf("\n\nEnter the car model: ");
scanf("%s", carmodel);
printf("\n\nEnter the car year: ");
scanf("%s", caryear);
printf("\n\nEnter the car type: ");
scanf("%s", cartype);
printf("\n\nEnter the quantity of models: ");
scanf("%d", &carQuantity);
if(start==NULL){
start=(struct node *)malloc(sizeof(struct node));
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start->prev=NULL;
start->next=NULL;
}else{
ptr=start;
start=(struct node *)malloc(sizeof(struct node));
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start->next=ptr;
}
}
void delete_first(){
struct node *ptr;
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
char modelNumber[MAX_WORD_LENGTH];
int carQuantity;
if(start==NULL){
printf("\n\nLinked list is empty.\n");
}else{
ptr=start;
printf("\nThe car for which the entry is removed is %s \n",ptr->data.carname);
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start=start->next;
free(ptr);
}
}
void display()
{
struct node *ptr=start;
int i=1;
if(ptr == NULL){
printf("\nLinklist is empty.\n");
}else{
printf("\nSr. No Make Model Year Type Quantity\n");
while(ptr != NULL){
printf("\n%d.\t%s %s %s %s %d\n", i,ptr->data.carname,ptr->data.carmodel,ptr->data.caryear,ptr->data.cartype,ptr->data.quantity);
ptr = ptr->next;
i++;
}
}
}
int main(void)
{
int ch;
do
{
printf("\n\n\n1. Insert \n2. Delete \n3. Display \n4. Exit\n");
printf("\nEnter your choice: ");
scanf("%d", &ch);
switch(ch)
{
case 1:
insert_first();
break;
case 2:
delete_first();
break;
case 3:
display();
break;
case 4:
exit(0);
default:
printf("\n\nInvalid choice. Please try again. \n");
}
} while(1);
return EXIT_SUCCESS;
}
You can't mix definitions of a struct with initialisation.
typedef struct criteriaselector{
const char *companyList[10];
companyList[0] = "Toyota"; // This bit needs to be elsewhere.
Instead, after you declare an instance of the struct, you'll then need to fill in the values. For example:
typedef struct criteriaselector{
const char *companyList[10];
}
.....
void some_function() {
CriteriaSelector criteriaselector;
criteriaselector.companyList[0] = "Toyota"
.... etc
However, it looks like you were intending to make a constant, rather than describe a structure. Instead of the whole struct definition, you can do:
const char *criteriaselector[10] = {"Toyota", "Honda" ... }
somewhere in global scope. This will declare a "global" array of constant strings.
As an aside, there's a little subtlety with the way that const works here. This declaration says "define an array of pointers to constant chars". This means that you can't change the strings themselves, but you can change the pointers. So, you can't do:
criteriaselector[1][0] = '\0' // changing a character inside a const string
But, you can do:
criteriaselector[1] = "some other string".
This probably isn't what you meant. Instead, we can say "define an array of constant pointers to constant strings", like this:
const char * const criteriaselector[10] = {"Toyota", "Honda" ... }
That way, you won't be able to change the contents of the string, or which strings are pointed to.
The comments on that question that I linked explain this in a bit more detail.
You cannot initialize variables inside a structure. This is because a struct defines a type and not a variable. You can initialize a structure members outside the structure definition using a structure variable (criteriaselector in your case) and .or -> access specifiers.
For eg.,
criteriaselector.companyList[0] = "Ford";

Resources