I keep getting this Segmentation Fault: 11 error and I don't know why.
My Code:
typedef struct Node* NodePtr;
struct Node
{
NodePtr next;
void *val;
};
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
int compare(void *one, void *two)
{
if(*(int*)one < *(int*)two)
return -1;
else if(*(int*)one > *(int*)two)
return 1;
return 0;
}
ListPtr create()
{
ListPtr blah = malloc(sizeof(struct List));
memset(blah, 0, sizeof(struct List));
return blah;
}
NodePtr scan(NodePtr head, void *obj)
{
NodePtr previous, current;
previous = head;
current = head->next; // Segmentation fault here!!
while(current != NULL && (compare(curry->val, obj) == -1))
{
previous = current;
current = current->next;
}
return previous;
}
int insert(ListPtr llist, void *obj)
{
NodePtr newobj = malloc(sizeof(struct Node));
NodePtr prevNode, nextNode;
prevNode = search(llist->head, obj);
nextNode = prevNode->next;
if((nextNode == NULL) || (compare(nextNode->val, obj) != 0))
{
prevNode->next = newobj;
newobj->next = nextNode;
return 1;
}
else
{
free(newobj);
}
return 0;
}
I thought head was not allocated, so I added malloc in create for blah->head, but still no luck.
I think the error is here after some debugging: current = head->next.
Any help would be appreciated! Thank you for your time!
EDIT: How I call insert:
int main(int argc, char *argv[])
{
ListPtr list = create();
int x = 2;
int *p = &x;
while(*p != 0)
{
printf("\nEnter a number: ");
scanf("%d", p);
if(*p != 0)
insert(list, p);
}
return 0;
}
You don’t appear to check whether the list is empty when you scan it. However, without a Minimum Complete Verifiable Example that tells us how you called the function, it is impossible to tell for sure what you did.
Update
Now that you have, that seems to be it. You create an empty list and search it inside your insert function. The search function dereferences the zeroed-out pointer in head, causing a segfault.
Try the following: first, check that your pointer is valid in each of your functions before you do anything with it. An empty list should fail every search. Second, for maximum portability, you want to set your head pointer to NULL (since a NULL pointer is not necessarily all-bits-zero on all implementations).
Related
I'm quite new to C and am still coming to grips with a lot of the syntax and idiosyncrasies. I'm not exactly sure what needs changing in order to make my code work but am open to any ideas. I understand that I need to utilize pointers in order to make this work but I am still lost on the specific implementation. I keep getting an error that my myList function is undeclared but I feel like I have declared it already. Is there something I am missing about how C works? Any help would be appreciated
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
}node;
node*linkedList ();
int main ()
{
struct linkedList* myList = (struct createList*)malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList ()
{
node* head;
node* current;
node*next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search(int value)
{
int index = 0;
node searchNode = head;
while(searchNode.next!= NULL)
{
searchNode = searchNode.next;
index++;
if (node.value = data)
{
break;
}
else {
index = -1;
}
}
return index;
}
}
I will be simplifying the explanations, so the terms that I will use might not be the correct one.
Proper and consistent indentation would always make your code easier to read and to fix. There were missing semi-colons too, you should watch out for that.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
} node;
node* linkedList();
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList()
{
node* head;
node* current;
node* next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode;
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead;
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search (int value)
{
int index = 0;
node searchNode = head;
while (searchNode.next != NULL)
{
searchNode = searchNode.next;
index++;
if(node.value = data)
{
break;
}
else
{
index = -1;
}
}
return index;
}
}
In main(), you should add the return 0; at the end of the function as it is an undefined behavior (AKA not a good thing to do). You could also change it to void main(), but it doesn't compile in clang.
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
You can't put a function within a function in C (nested functions). Put addNode(), getSize(), and search() outside the linkedList() function.
node* linkedList()
{
node* head;
node* current;
node* next;
}
addNode (int x)
{
node keephead = head;
...
}
int getSize ()
{
int counter = 0;
...
return counter;
}
int search (int value)
{
int index = 0;
...
return index;
}
linkedList() does literally nothing now and should be removed.
struct node* next;
} node;
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
...
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
void addNode (int x)
{
node keephead = head;
In main(), myList is the head of the currently empty linked-list, so it should be initialized to NULL. There's no linkedList data type, only node. Change it to:
node* myList = NULL;
You seem to be applying addNode(), getSize(), and search() to a variable, but C doesn't have that feature (C++ have it though). Add the linked-list head as an argument instead. addNode() needs the & address operator since it will be changing where the head starts.
addNode(&myList, 5);
addNode(&myList, 10);
addNode(&myList, 13);
printf("%d\n", search(myList, 10));
printf("The linked list is this big: %d\n", getSize(myList));
Update the function parameters of addNode(). In the while condition current.next = NULL and if statements, you were using an assignment operator instead of a comparison operator != or ==. You used the variables current and newnode, but never declared it anywhere in the function. There were lots of logic errors here. Change it to:
void addNode (node** head, int x)
{
node* current = *head;
node* newnode = malloc(sizeof(node));
newnode->data = x;
newnode->head = *head;
newnode->next = NULL;
if (*head == NULL)
*head = newnode;
else
{
while (current->next != NULL)
current = current->next;
//current is now the last node of linked list
current->next = newnode;
}
}
Do the same for the function parameters of getSize() and search(). Use node * instead for countNodes and searchNode. -> is the operator for accessing the members of a struct pointer. if statement should be put before it goes to the next node, as it would always skip the first node if left as it is. index should be put before the if statement so the index would update before it breaks out of the loop.
int getSize (node* head)
{
int counter = 0;
node* countNodes = head;
while (countNodes != NULL)
{
countNodes = countNodes->next;
counter++;
}
return counter;
}
int search (node* head, int value)
{
int index = 0;
node* searchNode = head;
while (searchNode != NULL)
{
index++;
if(searchNode->data == value)
break;
searchNode = searchNode->next;
}
if(searchNode->data != value)
index = -1;
return index;
}
Add the function prototypes before main().
void addNode (node** head, int x);
int getSize (node* head);
int search (node* head, int value);
int main()
{
node* myList = NULL;
Everything should work properly now.
Below I have made a simple Linked List in C. The code is currently producing a segmentation fault which I find odd because I was copying an example from our current book. The only thing I did to the code was put the code into the method "addToList". I'm aware the segmentation fault is coming from the method addToList but I do not know where I made a mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
Any help with telling me what is wrong or where I'm making the mistake would be greatly appreciated.
Look carefully at your code:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
You are not initializing the memory, so head->val and head->next are not
initialized. Because of that
while (current->next != NULL) {
current = current->next;
}
will loop an undefined amount of times. The first current->next is most
probably not NULL, so current = current->next get executed. At that point current is pointing to nowhere, hence the undefined behaviour which in your case leads to a segfault.
You have to initialized the memory like this:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
But you could also use calloc, which also sets the memory to 0, thus you don't have to initialize the values (in this case):
Node *head = calloc(1, sizeof *head);
if(head == NULL)
// error handling
You should always check for the return value of malloc/calloc/realloc.
Also note that the signature of the main function can be one of these:
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
edit
Another error I've noticed right now:
x = scanf("%d");
That's not how scanf works. You have to pass a pointer, scanf saves the
scanned value through the passed pointer. scanf returns the number of matched
values on success, in this case, success would be 1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
Also don't use the same variable x for the loop iteration and user input,
otherwise you are messing with the loop.
edit
User user3629249 wrote in the comment
good information, however the result will be the first entry in the linked list will contain garbage.
Better to declare head via: Node *head = NULL; and the function addToList() check for NULL and proceed accordingly.
That's right, the head element doesn't save any number in this way.
Option 1: double pointer
Here addToList receives a double pointer. The initialization of head occurs
when *head points to NULL. The function allocates memory for it, initializes
the memory, saves the value and returns. In the concurrent calls of addToList
*head won't be NULL, so addToList looks for the end of the list.
I've made small changes in the way you do malloc and realloc. Also I added
an implementation of freeList which should be used to free the memory:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
Option 2: addToList returns a pointer to the head
Here addToList takes a pointer to the head. If it's NULL, it allocates
memory and initializes like in the shown above. If head is not NULL, the
functions looks for the last element and the returns the head. On error the
function returns NULL.
Node *addToList(Node *head, int val) {
if(head == NULL)
{
head = calloc(1, sizeof **head);
head->val = val;
head->next = NULL;
return head;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return NULL;
current->next->val = val;
current->next->next = NULL;
return head;
}
int main(void)
{
int x;
Node *head = NULL, *tmp;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
tmp = addToList(head, val);
if(tmp == NULL)
{
fprintf(stderr, "Not enough memory\n");
freeList(head);
return 1;
}
head = tmp;
}
printList(head);
freeList(head);
return 0;
}
I keep getting Segmentation Fault (core dumped) run time error and I can't figure out why.
My code:
struct Node
{
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr create()
{
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
int insert(ListPtr list, void *obj)
{
NodePtr newObj = malloc(sizeof(struct Node));
//Cast next as a self referencing Node
newObj->next = (NodePtr) newObj->next;
//Point to beginning of list
NodePtr current = list->head;
if(list->head == NULL)
{
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int x = 2;
int *p = &x;
ListPtr thing = create();
insert(thing, p);
return 0;
}
The error is here: list->head->next = newObj after some debugging. I thought I had to allocate memory for list->head->next, but when I added the code in for that it still gave me the same error. Am I casting it wrong or not allocating memory correctly? Any help would be appreciated, thanks!
Just put this together, runs fine.
#include <stdlib.h>
#include <stdio.h>
struct Node {
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List {
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr CreateList() {
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
void Insert(ListPtr list, void *obj) {
// create and initialize new node
NodePtr newObj = malloc(sizeof(struct Node));
newObj->val = obj;
newObj->next = NULL;
//Point to beginning of list
NodePtr curr = list->head;
// Add node to the list
if(curr == NULL) // if no head node, make newObj the head node
{
list->head = newObj;
}
else{ // otherwise traverse the list until you find the last node (the one that points to a null as the next)
while(1) {
if(curr->next != NULL) {
curr = curr -> next;
} else {
curr->next = newObj;
}
list->head = newObj;
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
}
}
}
int main() {
int x = 2;
int *p = &x;
ListPtr thing = CreateList();
Insert(thing, p);
return 0;
}
You check if list->head is NULL and then do some operations with that. Change that to if(list->head != NULL)
{
...
}
At a thought, malloc does not guarantee allocated memory is empty. It's good practice to set all values where they matter after allocation.
list->head is probably not null
also : newObj->next = (NodePtr) newObj->next;
doesn't set to a rational value, it sets to whatever memory was set - were you intending newObj->next = (NodePtr) newObj; ?
list->head should not be referenced if null. list->head->next will only be valid if it's not null.
if you actually want to build a list,
newObj->val = obj;
if (list->head == NULL) { newObj->next = list->head; }
list->head = newObj;
either that or travel down list->head->next chain until next is null, and set that to be newObj->next. If that way then it's possibly a good idea, newObj->next should be set to NULL and not itself.
Might want to figure out how your list will behave - is it circular? does it grow from the head (list->head) or tail (last ->next) ? Do you spot the tail when listObject->next == NULL or when listObject->next == listObject ?
I realize that this answer is mostly stylistic. But I do think that (bad) style and (bad) habits are an (important) part of (bad) programming. Summing it up ...
(in most cases) typedefs are not needed; they just introduce an alias for something that already existed.
[rule of seven] human readers have a limited amount of identifiers ("names") that they can keep track of. This could be 7. Minimising the number of distinct words makes reading easier.
also, the reader has to remember that xPtr and xNode are related (typeof *xPtr === typeof xNode)
when reading source code, keywords and special character tokens (such as operators) don't count as an identifier, since you do not have to remember them. (Syntax-highligting helps, too)
if there is only one way of expressing your program, there is no possibility for errors like iPtr *p; p = (qPtr) malloc (sizeof xNode);
creating yet another struct (+typedefs for it), just to accomodate a root pointer will clobber up your mental namespace even more.
Now a rework of the (intended) code:
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
void *payload;
};
struct node *root=NULL;
void initialize() { /* nothing .... */ }
int insert(struct node **pp, void *pv) {
struct node *p;
p = malloc(sizeof *p);
if (!p) { /* handle error */ return -1; }
p->payload = pv;
p->next = *pp;
*pp = p;
return 1; /* inserted one element */
}
int main(void)
{
int i;
i=666;
/* note: this function call will pass a pointer to a local variable `i`
** to the insert() function, which will remember it.
** This is generally a bad idea, to say the least.
*/
insert( &root, &i);
return 0;
}
i am writing a Dictionary using linked list in C, and all my functions work except my delete function, which is shown below along with all other necessary code. Every time i try to run my program as soon as it reaches a line in which it must delete a node, it gives me the error: Segmentation Fault (core dumped) which means it has something to do with the memory allocation or a null pointer i think. I know that the rest of my code works. All and any help is appreciated! :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"Dictionary.h"
// NodeObj
typedef struct NodeObj{
char* key;
char* value;
struct NodeObj* next;
} NodeObj;
// Node
typedef NodeObj* Node;
// newNode()
// constructor of the Node type
Node newNode(char* key, char* value)
{
Node N = malloc(sizeof(NodeObj));
assert(N!=NULL);
// if(key!=NULL && value!=NULL){
N->key = key;
N->value = value;
N->next = NULL;
// }
return(N);
}
// DictionaryObj
typedef struct DictionaryObj{
Node head;
int numItems;
} DictionaryObj;
// newDictionary()
// constructor for the Dictionary type
Dictionary newDictionary(void){
Dictionary D = malloc(sizeof(DictionaryObj));
assert(D!=NULL);
D->head = NULL;
D->numItems = 0;
return D;
}
Node findKey(Dictionary D, char*key){
Node N;
N = D->head;
while(N != NULL){
if(strcmp(N->key,key)==0){
return N;
}
N = N->next;
}
return NULL;
}
char* lookup(Dictionary D, char* k){
if(findKey(D, k)==NULL){
return NULL;
}else{
Node N;
N = findKey(D, k);
return N->value;
}
}
void delete(Dictionary D, char* k)
{
if(lookup(D,k) == NULL){
fprintf(stderr,
"KeyNotFoundException: Cannot delete non-existent key\n");
exit(EXIT_FAILURE);
}
int check = strcmp(D->head->key, k);
if(check == 1){
D->head = D->head->next;
return;
}
Node cur;
Node prev;
cur = D->head;
prev = NULL;
while( cur != NULL){
int ret1;
ret1 = strcmp(cur->key, k);
while( ret1 == 0){
prev = cur;
cur = cur->next;
}
}
prev->next = cur->next;
D->numItems--;
}
The NodeObject should store copy of the string and care for deleting it:
typedef struct Node Node;
struct Node {
Node *next;
char *key, *value;
};
Node* newNode(char* key, char* value) {
assert(key && value);
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->next = NULL;
node->key = strdup(key);
node->value = strdup(value);
}
void delNode(Node* node) {
free(node->key);
free(node->value);
}
Consider using the original code (without that strdup) in this scenairo:
Node* prepare() {
char key_buf[20]; strcpy(key_buf, "mykey");
char val_buf[20]; strcpy(val_buf, "myval");
return newNode(key_buf, val_buf);
}
void examine(Node* node) {
printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
examine(prepare());
}
the above code would crash because Node would have pointers to stack (in your case without that strdup), but key_buf+val_buf were only valid inside prepare() (garbage outside and therefore inside examine() - node->key points to random data).
I am having trouble with inserting items in linked list. All the elements end up having the same *data content that is inserted in the last. The program compiles successfully. I use gcc and gdb.
I am new to coding so please mention troubles if any that you see in my programming style.
typedef struct Node{
void* data;
struct Node* next;
} *node;
node allocate(){
node current = malloc(sizeof(struct Node));
current->data = NULL;
current->next = NULL;
return current;
}
void insert(node *head, void *data){
// if head has no data then set the data on head and return
if(((*head)->data == NULL)&&((*head)->next == NULL)){
(*head)->data = data;
return;
}
node newHead = allocate();
newHead->data = data;
newHead->next = *head;
*head = newHead;
//printf("Node Data : %d\tNext Node Data : %d",
//*(int *)((*head)->data), *(int *)((*head)->data));
}
int main(int argc, char *argv[]){
node head = allocate();
int count = inputSequence(&head);
int *aod = calloc((size_t) count, sizeof(int));
generateAOD(head, aod);
if(checkJolly(aod, count) == TRUE)
printf("Jolly\n");
else
printf("Not Jolly\n");
return 0;
}
int inputSequence(node *input){
int *num = malloc(sizeof(int));
int count = 0;
while((scanf("%d", num) != EOF)){
insert(input, (void *)num);
count++;
}
traverse(*input, fn);
return count;
}
Your insert logic is non-existant. And you're literally making your life harder by attempting to manage a linked list in the fashion you're using.
The head pointer itself should indicate whether the list is empty. If it is NULL, its empty. If it isn't, there's data. Code the insertion logic accordingly.
And your inputSequence is utterly broken. It only allocates ONE data point, then uses the same data allocation for every insertion. You need one for each insertion.
First, change allocate() to accept the data being inserted. It will make the remaining code less cluttered:
node allocate(void *data)
{
node current = malloc(sizeof(*current));
current->data = data;
current->next = NULL;
return current;
}
Second, insert by allocating a new node as needed.
void insert(node *head, void *data)
{
node p = allocate(data);
p->next = *head;
*head = p;
}
Next, fix inputSequence() to properly allocate memory for each entry:
int inputSequence(node *input)
{
int count = 0;
int num = 0;
// note: check for number of params *successfully* parsed.
// if it isn't 1, its time to leave the loop.
while(scanf("%d", &num) == 1)
{
int *data = malloc(sizeof(num));
*data = num;
insert(input, data);
++count;
}
return count;
}
And lastly, make sure your head pointer is initially NULL in main().
int main(int argc, char *argv[])
{
node head = NULL;
// load linked list
inputSequence(&head);
// ... the rest of your code....;
return 0;
}
With the above, the logical answer of "Is my list empty" is simply if (!head) Further, this makes things like traversal trivial.
void traverse(node ptr, void (*pfn)(void *))
{
while (ptr)
{
pfn(ptr->data);
ptr = ptr->next;
}
}
Freeing the list is equally trivial:
void destroy(node *head)
{
while (*head)
{
node p = *head;
*head = p->next;
free(p->data);
free(p);
}
}
typedef struct Node{
void* data; // Make it as int or any other data type
struct Node* next;
} *node;
In function inputSequence() you are allocating memory for num at the very beginning and making node->data point to this memory each time you are adding a node. Hence data pointer of each node of your linked list points to the same memory location and hence contains the same value.
If you still want to continue with data as a void pointer, allocate num for each iteration of the while loop and pass this to insert function.
while((scanf("%d", num) != EOF)){
num = malloc(sizeof(int);
insert(input, (void *)num);
count++;
}