Simple Linked List C code Segmentation fault - c

I am making a linked list program for my basic C assignment.
However, I will always get the force closed error on .exe and get a segmentation fault on Ubuntu.
I tried to break it down and rewrite but I have no idea where the code fails.
I'd appreciate your help.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node{
char name[20];
int mark;
struct node *next;
};
struct node *addnode(char name[], float mark);
int main(void){
int j = 0;
char StdName[10];
float StdMarks;
struct node *head = NULL;
struct node *curr = NULL;
head = curr = addnode('\0',0.0);
for(j=0; j<3; j++){
printf("\nEnter StdName >>");
printf("\nMarks for %s >>", StdName);
curr -> next = addnode("", 5.5);
curr = curr->next;
}
curr = head -> next;
j = 0;
printf("\nnode\tName\tMarks");
while(curr){
printf("\n%d\t%s\t%5.2f", j++, curr->name, curr->mark);
curr=curr->next;
}
return 0;
}
struct node *addnode(char name[], float mark){
struct node *temp;
temp=(struct node*)malloc(sizeof(struct node));
strcpy(temp->name,name);
temp->mark=mark;
temp->next=NULL;
return (temp);
}

A few mistakes:
'\0' is not a char[], but a char whose value is 0 and converted to a char* (NULL pointer). Use "" for an empty string. The compiler should have emitted a warning for this. Compile with warning level at highest and treat warnings as errors (so you cannot ignore them). For gcc the flags are -Wall -Werror.
StdName is not initialised and is never populated but is used in a printf("%s") call.

The first node you add you use a single char '\0' for name, when you should pass a string:
head = curr = addnode("", 0.0);
And also this doesn't point to the first node, it points to the second one:
curr = head -> next;
Should be:
curr = head;
I don't know what you intended to do with StdName but as hmjd said, it should be initialized to some value.
char StdName[] ="stdname";

head = curr = addnode('\0',0.0); line is invalid. Your addnode function expects a pointer to characters array as first parameter. '\0' is an integer value equal to 0. You pass the name to strcpy which uses it as a pointer to source data. Since the pointer is 0 (== NULL), you get a crash.

Related

runtime error: null pointer passed as argument 1, which is declared to never be null

I wrote a program that creates Linkedlists with two values.
It worked when I just had int values in it but now that I added char* this error messages shows
runtime error: null pointer passed as argument 1, which is declared to never be null
As mentioned before this worked fine until I added char* to the constructor and the struct. Not sure where it goes wrong as the error seems to come from different lines in the code everytime I run it... So what do i need to change ?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
typedef struct node {
int val;
char* name;
struct node *next;
} node_t;
void addFirst(int value, char* word, node_t** nd) {
//initialize new node, allocate space, set value
node_t * tmp;
tmp = malloc(sizeof(node_t));
tmp->val = value;
strcpy(tmp->name, word);
//let the new nodes next pointer point to the old head
tmp->next = *nd;
//Make tmp the head node
*nd = tmp;
}
int findItem(int value,char* word, node_t *nd) {
if(nd->val == value)
return 0;
while(nd->next != NULL) {
if(nd->val == value && strcmp(word, nd->name) == 0)
return 0;
if(nd->next != NULL)
nd = nd->next;
}
return -1;
}
int main (void) {
node_t *head = malloc(sizeof(node_t));
head->val = 0;
strcpy(head->name, "");
head->next = NULL;
addFirst(15, "word", &head);
addFirst(14,"word2", &head);
printf("%i \n", findItem(15, "word", head));
}
The problem is in strcpy(head->name, "");. Here, you;re trying to use the memory location pointer to by head->name, but you never assigned a valid memory to it.
You need to make sure that the pointer points to a valid memory location, before you write to / read from that memory location. Attempt to access invalid memory invokes undefined behavior.
This is applicable for other uninitialized instances of name, too.
If you can live with POSIX standard, instead of strcpy(), you can make use of strdup()

Pointer with double pointer

Why cant I assign a pointer to a double pointer's pointer? I get segmentation fault every time.
#include <stdio.h>
int main() {
int **pointer1, *pointer2, *pointer3, var;
var = 10;
pointer3 = &var;
pointer1 = &pointer3;
pointer2 = *pointer1; //correcting my mistake, so this is now correct?
return 0;
}
The code I was actually working on, practicing linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t **head, *temp;
*head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, head);
}
temp = *head;
/*while (temp != NULL) { //here is the problem, if I remove this
//I get segmentation fault but it runs
printf("%d ", temp->num); //runs fine when I include it
temp = temp->next;
}*/
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Just like what I put in the code comment, the above version of my code gets segmentation fault when I compile it without the while loop. But weirdly enough, it works fine once I include the while loop. After fiddling around, I suspect the culprit to be the double pointer in which I tried to assign the secondary address into a regular pointer.
But this version actually runs fine:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t *head, *temp;
head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, &head);
}
temp = head;
while (temp != NULL) {
printf("%d ", temp->num);
temp = temp->next;
}
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Over here I passed the address into the linked list function and essentially I'm doing the same thing but without the double pointer.
On a side note, I have seen many different implementations of linked lists. Mine requires the double pointer because I'm using a void insert(int, **node_t), but there are versions which returns the address and updates the head: node_t* insert(int, *node_t) and Global linked list: void insert(int). Just wondering which versions are actually recommended, easier to debug and beginner friendly.
Your first example segfaults because *pointer1 (and pointer1 before it) isn't pointing to anything. It's an uninitialized pointer that points to random garbage data in memory.
Trying to dereference such a pointer (**pointer1 = 10;) results in a segfault.
A solution to make your first example work would be to allocate some memory for the data you're trying to store :
int **pointer1, *pointer2;
int *data = malloc(sizeof(int));
pointer1 = &data;
**pointer1 = 10;
pointer2 = *pointer1;
free(*pointer1); //or free(data)
When you do this:
**pointer1 = 10;
What this says is "take the address stored in pointer1, dereference that address, take the address stored there, dereference again, and store the value 10 at that location".
It looks something like this:
pointer1
------- ------- ------
| .--|---->| .--|--->| 10 |
------- ------- ------
You're getting a segfault because pointer1 doesn't currently point anywhere.
This could work if you do something like this:
int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;
In the case of the two "real" code snippets, the problem with the first piece of code is that you pass head uninitialized to insert, which then subsequently dereferences head. This is the same problem as above. The same thing happens again in main because head is still uninitialized after calling list because it was passed by value. The second piece of code works because you pass the address of head to insert, so subsequently dereferenced it is valid.

trying to copy a c string in a struct using only C

I'm trying to insert a hard coded string into a char array value in a struct using only C, so I used memcpy, following the example in another post. But for some reason, I keep getting what looks like an address as output, I'm not sure why.
my console prints out: [ (2,7532592) (1,7524424) ] and other long numbers like that every time. I've checked so many examples on how to copy a sequence of characters into a c string, and it seems like this one was exactly the same. I might just be having trouble understanding pointers. Im not sure why it's spitting out the address value. Can anyone point out what I'm doing wrong? I apologize for any lack of knowledge on my part. My shortened down code is below:
struct node
{
int key;
char month[20];
struct node *next;
};
struct node *head = NULL;
struct node *current = NULL;
//display the list
void printList()
{
struct node *ptr = head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL)
{
printf("(%d,%d) ",ptr->key,ptr->month);
ptr = ptr->next;
}
printf(" ]");
}
//insert link at the first location
void insertFirst(int key, char * month)
{
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
memcpy(link->month, month, 20);
link->month[19] = 0; // ensure termination
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
int main() {
insertFirst(1,"Jan");
insertFirst(2,"March");
printf("Original List: ");
//print list
printList();
}
You are printing the pointer ptr->month, not the actual string.
Try: printf("(%d,%s) ",ptr->key,ptr->month); (%s instead of %d).
Try
printf("(%d,%s) ",ptr->key,ptr->month);
instead for the "curious output" problem.

C - Unable to free memory allocated within a linked list structure

Consider the following code snippet
struct node {
char *name;
int m1;
struct node *next;
};
struct node* head = 0; //start with NULL list
void addRecord(const char *pName, int ms1)
{
struct node* newNode = (struct node*) malloc(sizeof(struct node)); // allocate node
int nameLength = tStrlen(pName);
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
newNode->m1 = ms1;
newNode->next = head; // link the old list off the new node
head = newNode;
}
void clear(void)
{
struct node* current = head;
struct node* next;
while (current != 0)
{
next = current->next; // note the next pointer
/* if(current->name !=0)
{
free(current->name);
}
*/
if(current !=0 )
{
free(current); // delete the node
}
current = next; // advance to the next node
}
head = 0;
}
Question:
I am not able to free current->name, only when i comment the freeing of name, program works.
If I uncomment the free part of current->name, I get Heap corruption error in my visual studio window.
How can I free name ?
Reply:
#all,YES, there were typos in struct declaration. Should have been char* name, and struct node* next. Looks like the stackoverflow editor took away those two stars.
The issue was resolved by doing a malloc(nameLength + 1).
However,If I try running the old code (malloc(namelength)) on command prompt and not on visual studio, it runs fine.
Looks like, there are certain compilers doing strict checking.
One thing that I still do not understand is , that free does not need a NULL termination pointer, and chances to overwrite the allocated pointer is very minimal here.
user2531639 aka Neeraj
This is writing beyond the end of the allocated memory as there is no space for the null terminating character, causing undefined behaviour:
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
To correct:
newNode->name = malloc(nameLength + 1);
if (newNode->name)
{
tStrcpy(newNode->name, pName);
}
Note calling free() with a NULL pointer is safe so checking for NULL prior to invoking it is superfluous:
free(current->name);
free(current);
Additionally, I assume there are typos in the posted struct definition (as types of name and next should be pointers):
struct node {
char* name;
int m1;
struct node* next;
};

malloc() causing EXC_BAD_ACCESS error in Xcode

I am trying to implement the Linked List data structure for my college course, but on executing the code the following line produces an EXC_BAD_ACCESS(code=1, address=0x8) error.
temp->next = (ptrtonode) malloc(sizeof(struct node));
Following is the code in its entirety.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *ptrtonode;
typedef ptrtonode header;
struct node
{
int data;
ptrtonode next;
};
ptrtonode create(int n)
{
int i;
header temphead = NULL;
ptrtonode temp = temphead;
for(i=0;i<n;i++)
{
temp->next = (ptrtonode) malloc(sizeof(struct node));
printf("Enter data for node %d: ", i+1);
scanf("%d", &temp->next->data);
temp = temp->next;
}
temp->next = NULL;
return temphead;
}
int main(int argc, const char * argv[])
{
header head;
int n;
printf("How many nodes do you wish to create?");
scanf("%d", &n);
head = create(n);
}
Any help would be appreciated.
Thanks all!
On first iteration of the for loop inside the create() function temp is NULL, which is then dereferenced causing the failure (not malloc() causing the failure). You will need to restructure the code slightly to prevent dereferencing a NULL pointer.
Other points:
casting the return value of malloc() is not required.
check the result of scanf() to ensure n was assigned a valid integer (and confirm that the int is positive):
/* scanf() returns the number of assignments made,
which in this case should be 1. */
if (1 == scanf("%d", &n) && n > 0)
{
/* 'n' assigned a sensible value. */
}

Resources