C: Linked list bad access of memory - c

I have to work on linked lists and get a bad access error even before something happens in my main. I don't know what's wrong. I am relatively new to dynamic memory management. It would be nice if someone could take a look on the functions. The declaration was given by the professor, so we have to return a DoubleNote*.
My code is below:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
double var;
struct node *next;
} DoubleNode;
DoubleNode* insertFirst(DoubleNode* head, double d){
DoubleNode* new_head;
new_head = (DoubleNode*)malloc(sizeof(DoubleNode));
if (new_head == NULL) {
printf("Error: Allocating memory for new node failed!");
exit(1);
}
new_head->var = d;
new_head->next = head;
head = new_head;
return head;
}
DoubleNode* inserLast(DoubleNode* head, double d){
DoubleNode* current = head;
while (current != NULL) {
current = current->next;
}
current->next = (DoubleNode*)malloc(sizeof(DoubleNode));
if (current->next == NULL) {
printf("Error: Allocating memory for new node failed!");
exit(1);
}
current->next->var = d;
current->next->next = NULL;
return head;
}
DoubleNode* inverseDoubleListCon(DoubleNode* head){
DoubleNode* current = head; // iteration variable starts on head of old list
DoubleNode* conHead = current; // Head of the new list
while (current != NULL) {
current = current->next; //iteration step
DoubleNode* newConHead = (DoubleNode*)malloc(sizeof(DoubleNode)); //allocating memory for new head
if (newConHead == NULL) {
printf("Error: Allocating memory for new node failed!");
exit(1);
}
newConHead = current; // new_head is the next variable in the old list
newConHead->next = conHead; //new head points to old head of the new list
conHead = newConHead; // new head is set
}
return conHead;
}
void printList(DoubleNode* head){
DoubleNode* current = head;
while (current != NULL) {
printf("%lf\n", current->var);
current = current->next;
}
}
int main(){
DoubleNode* head = NULL;
DoubleNode* inverseHead = NULL;
double d;
int i;
int sizeOfList;
printf("Insert amount of variables: \n");
scanf("%d", &sizeOfList);
for (i = 0; i < sizeOfList; i++) {
printf("Insert variable for node [%d]: \n", i);
scanf("%lf", &d);
head = insertFirst(head, d);
}
printList(head);
inverseHead = inverseDoubleListCon(head);
printList(inverseHead);
return 0;
}

Firstly sizeOfList is not initalised. You need to add code to get the value of the size from the user.
You are also not updating the value of the head pointer from the insertFirst function. The code below should help.
DoubleNode* head= NULL;
// Code to get the value of sizeofList
for (i = 0; i < sizeOfList; i++)
{
...
head = insertFirst(head, d);
}
The reverse function is overly complicated. You are allocating memory in newConHead which is not required for reversing a linked list.
I would suggest a rewrite along the lines of How to reverse a singly linked list using only two pointers? or http://www.geeksforgeeks.org/write-a-function-to-reverse-the-nodes-of-a-linked-list/

Related

How to change the data of a node in Linked list in C?

struct:
//linked list
struct list
{
int32_t data;
struct list *next;
};
struct list *head;
at first, initialize linked list (every node be 0):
void initLinkedList(int size)
{
head = (struct list*)malloc(sizeof(struct list)*size);
struct list *current = head;
for(int i = 0; i < size; i++)
{
(current+i)->data= 0;
}
}
function:
void changeNode(int32_t element, int index)
{
struct list *current = head;
for (int i = 0; i < index; i++)
{
current = current->next;
}
current->data= element;
}
so basically, I want to create a linked list with size nodes, then change the data of the node through function.
But I'm getting Segmentation fault at this line in function:
current->localVar = element;
So, how can I change the data of a node without inserting a new one?
You must consider whether you have requested to change an index that doesn't exist in your list, but otherwise you are close. You are not iterating your initLinkedList in a traditional manner (you are treating the list like an array) As a side-note: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?.
Let's start with your initLinkedList function. You have declared head globally (assuming) and then go to fill your list with zeros. In doing so, you never initialize any of your ->next pointers. You don't end up with a linked-list -- you have a block of allocated nodes.
You should iterate current = current->next; and set each ->next pointer, not just use the offset +i. You are able to initialize your data like that due to allocating all nodes in a continual block -- but any node added later will not be contiguous in memory and none of your ->next pointers are initialized.
Now on to your changeNode function. You must fix your initLinkedList to initialize the ->next pointers. Then you need to change the return type from void to struct list* so you can return a pointer to the changed node on success or NULL on failure. Currently, you have no way of knowing if your change succeeded or failed.
Making the changes you could do:
struct list *changeNode (int32_t element, int index)
{
struct list *current = head;
for (int i = 0; i < index; i++) {
if (!current->next) {
fputs ("error: request exceeds no. of nodes in list.\n", stderr);
return NULL;
}
current = current->next;
}
current->data = element;
return current;
}
Look things over and let me know if you have further questions.
So, here void initLinkedList(int size) you aren't creating/initializing a linked list instead you are declaring an array of type struct list dynamically with size no. of elements and then you are initializing all of them with value 0.
To initialize your linked list code this:
void initLinkedList(int size)
{
if((head = (struct list*)malloc(sizeof(struct list)*size)) == NULL)
{
printf("Memory Unavailable.\n");
exit(1);
}
struct list *current = head;
for(int i = 0; i < size; i++)
{
current->data = 0;
if ((current->next = (struct list*)malloc(sizeof(struct list))) == NULL)
{
printf("Memory Unavailable.\n");
exit(2);
}
current = current->next;
}
current->next = NULL;
}
Then to changeNode, code this:
void changeNode(int element, int index)
{
struct list *current = head;
int count = 0;
while(count != index)
{
if(current->next)
current = current->next;
count++;
}
current->data = element;
}
Here I'm adding another function to print the linked list:
void print(struct list *head)
{
if(head->next)
{
printf("%d", head->data);
head = head->next;
print(head);
}
}
main():
int main(void)
{
initLinkedList(5);
changeNode(5, 4);
print(head);
delete(head);
printf("Memory freed.\n");
return 0;
}
Now you can see the Sample Output:
00005
Memory freed.
One more thing, if you are confused about this:
if ((current->next = (struct list*)malloc(sizeof(struct list))) == NULL)
I can help you. In the above line of code, we're allocating memory to current->next and checking if memory is allocated successfully or not.
Freeing the memory allocated to linked list using delete() function:
void delete( struct list *head )
{
struct list *current = head;
struct list *next = NULL;
while(current != NULL)
{
next = current->next;
free(current);
current = next;
}
}

How to return lists in c functions?

As the title says I need to write a function which fill a list with int typed by the user, and later on print them, but i'm having troubles with the insert function, which does not actually put the values typed in the list. Here's the code:
the typedefs:
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
and the functions:
list lins(list l)
{
int i;
list root = NULL;
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
l = (list)malloc(sizeof(item));
l->value = i;
l->next = root;
root = l;
} while (i != 0);
return l;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
Sorry if my code is poorly written but I'm having a hard time understanding the concept of lists.
Edit: added functions calls
main()
{
lins(l);
showlist(l);
}
Edit 2: here's the output of the code:
output
Edit 3: Here's the sample of code my professor give us to work with lists:
http://www.mediafire.com/file/wj152pw1ojkxf1j/10a_-Liste-_2018.pdf
Your insertion function inserts in reverse order. That is because you assign root to l->next and l to root. Also the number 0 is included in the list when the user tries to end the insertion process.
In main(), you don't seem to assign the return value of the function lins() to a variable, and if you passed l declared as List l = NULL; to the function lins(), then a copy of it will be used, and so, the original variable won't be altered. What you really need is something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
list lins(void)
{
list node = NULL;
list root = NULL;
list tail = NULL;
printf("inserire dati ('0' per terminare):\n");
int i;
scanf("%d", &i);
while(i != 0)
{
node = (list)malloc(sizeof(item));
node->value = i;
node->next = NULL;
if (!root)
root = node;
else
tail->next = node;
tail = node;
scanf("%d", &i);
}
return root;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
int main(void)
{
list head = lins();
showlist(head);
system("pause");
return 0;
}
Of course, I should point out that you should free the list once you are done with it.
First of, I see no point in passing item *l as an argument to lins function.
The root or better, head of the list should not be changed once you assign something to it, unless you want to delete the list.
void lins(item **head){
item *new_node = malloc(sizeof(item));
int i;
if(!new_node){
printf("Memory allocation failed!\n");
exit(1);
}
scanf("%d", &i);
new_node->value = i;
new_node->next = NULL;
node *temp = *head;
if(!temp)
*head = new_node;
else{
while (temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
return ;
}
After you write lins like this, showlist can look as follow:
void showlist(item *head){
printf("List is: \n");
do{
printf("%d", head->value);
head=head->next;
}while(head!=NULL);
}
As for the main function you need to declare the head first.
int main(){
item *head = NULL;
lins(&head);
showlist(head);
return 0;
}
more detailed explanation to follow...
So from what I understand, you want to prepend to your linked-list. I will try to use your typedefs, though many comments have given better options to use, you could change the implementation later.
Realise that lins(list l) is never utilising the value of the parameter l passed to it. That is overriden by the malloc. It is prepending elements to the list, and finally returns the new head of your list. That new head has to be passed to showlist() for printing. What you might be doing is initialising one element of the list in main, and passing that to lins and showlist. lins doesnt bother with the parameter and returns a completely new list, but when you pass that old list to showlist it is interpreted as an empty list.
So you can simply change usage of lins to be used as a creator of linked-lists.
So declaring list lins() {...} and using it in main() like this should work:
int main() {
list l;
l = lins();
showlist(l);
return 0;
}
struct list_element {
int value;
struct list_element *next;};
typedef struct list_element * list;
void lins(list *l){
list tmp = NULL;
list last = *l;
int i;
if (last){
while(last->next){ // go to last child of list
last = last->next;
}
}else{
last = (list)malloc(sizeof(struct list_element));
}
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
last->value = i;
last->next = (list)malloc(sizeof(struct list_element));
last = last->next;
} while (i != 0);}
void show(list li){
list tmp = li;
if(li){
while(tmp){
printf("%d at %p\n",tmp->value, tmp);
tmp = tmp->next;
}
}}
int main(){
list a = (list)malloc(sizeof(struct list_element));
lins(&a);
show(a);
return 0;}

Linked List making segmentation fault

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;
}

Freeing Memory after Linked List Removal

I am learning C in my free time. I am familiar with C#, Java, and Python. As an exercise, I wrote a linked list in C. It functions correctly, has error handling, etc.
However, I am trying to fix memory leaks. I know that C does not have automatic garbage collection. So how do I "free" a member of a list after I have removed it? I wrote a function called removeAllList(). The function removes the member from the list successfully, but I know that the memory for that member is still allocated. I have tried using the free([myArgument]) function, but it results in infinite loops. Can you show where I would use the free() function to successfully deallocate memory for the removed member in my code?
#include<stdio.h>
#include<stdlib.h>
struct Member{
int data;
struct Member *next;
};
struct List{
int size;
struct Member *root;
};
struct Member *createMember(int i){
struct Member *new;
new = malloc(sizeof(struct Member));
new->data = i;
new->next = NULL;
return new;
}
struct List *createList(int i){
struct List *new;
new = malloc(sizeof(struct List));
new->root = createMember(i);
new->size = 1;
return new;
}
void printList(struct List *list){
struct Member *current = list->root;
//error handling for empty list
if(list->size < 1){
printf("Error: List is empty");
}
//if list is not empty
else{
printf("List size: %i\nContents: ", list->size);
while(current->next != NULL){
printf("%i, ", current->data);
current = current->next;
}
printf("%i\n", current->data);
}
}
void addList(struct List *list, int i){
struct Member *current = list->root;
while(current->next != NULL){
current = current->next;
}
current->next = createMember(i);
list->size++;
}
void removeAllList(struct List *list, int i){
struct Member *current = list->root;
struct Member *prev = list->root;
if(list->size < 1){
//list is empty, end function now
return;
}
//remove all matching list head
while(current->data == i){
if(list->size <= 1){
list->root = NULL;
list->size--;
//list is empty, end function now
return;
}
else{
list->root = current->next;
current = list->root;
list->size--;
}
}
current = current->next;
//remove all matching list body
while(current->next != NULL && list->size > 1){
if(current->data == i){
prev->next = current->next;
list->size--;
}
prev = current;
current = current->next;
}
//remove all matching list tail
if(current->data == i && list->size > 1){
prev->next = NULL;
list->size--;
}
}
main(){
struct List *myList;
myList = createList(4);
addList(myList, 12);
addList(myList, 9);
addList(myList, 4);
addList(myList, 43);
addList(myList, 4);
printList(myList);
removeAllList(myList, 4);
printList(myList);
}
You shouldn't make things that consume memory NULL. You need to free() them like this: free(mynode->next); but only when you're sure there was a malloc() call before.
In your code, you need to use free(list->root); instead of list->root = NULL; and free(prev->next); instead of prev->next = NULL;

No program output in C [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
#include<stdio.h>
#include<malloc.h>
typedef struct node_t {
int i;
struct node_t* link;
} node;
node* head = NULL;
int main() {
int i = 10;
node* temp = NULL;
head = (node *)malloc(sizeof(node));
temp = (node *)malloc(sizeof(node));
if(temp == NULL) {
printf("\n malloc for temp node failed! \n");
}
else {
/* linked list logic to add the elements in the beginning */
while(i<=10) {
temp->i = i;
temp->link = NULL;
if(head == NULL) {
head = temp;
}
else {
temp->link = head;
head = temp;
}
i++;
}
}
for(temp = head; temp->link != NULL; temp = temp->link) {
printf("\n The data is:%d \n",temp->i);
}
free(temp);
free(head);
return 0;
}
I'm trying a simple linked list program. I'm not getting the output.
1) You have to allocate node (tmp) each time you are assigning value to tmp. and not allocate only one time the tmp. See the following fixed code to see how to do it
2) the following for loop is wrong:
for(temp = head; temp->link != NULL; temp = temp->link) {
This for loop is fixed in the following code
3) for the free you have to browse the whole linked list and then free each node. see the following fixed code.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct node_t{
int i;
struct node_t* link;
}node;
node* head = NULL;
int main(){
int i = 1;
node* temp = NULL;
/* linked list logic to add the elements in the beginning */
while(i<=10){
temp = (node *)malloc(sizeof(node));
if(temp == NULL){
printf("\n malloc for temp node failed! \n");
exit(1);
}
temp->i = i;
temp->link = NULL;
if(head == NULL){
head = temp;
}
else{
temp->link = head;
head = temp;
}
i++;
}
for(temp = head; temp != NULL; temp = temp->link){
printf("\n The data is:%d \n",temp->i);
}
while (head!=NULL)
{
temp = head->link;
free(head);
head = temp;
}
}
You seem to have an infinite loop! (the value of i is not changed)
You are not changing the value of variable i in the while loop as a result you never come out of the while loop.
You need something like:
int i=1;
while(i<=10){
// insert i in loop
i++;
}
You are not changing the value of loop variable i.e. i.
Also you need to do malloc inside while loop to create separate nodes. Right now, your code is modifying the same node again and again.
In addition to the node about the infinite loop, since you never modify the value of i there's something else that's wrong.
22 /* linked list logic to add the elements in the beginning */
23 while(i<=10){
24 temp->i = i;
25 temp->link = NULL;
26 if(head == NULL){
27 head = temp;
28 }
29 else{
30 temp->link = head;
31 head = temp;
Look at what you are doing in this loop. If head is NULL (it's very unlikely to be, since you allocated it back in line 15, although it's possible that the allocation could fail) you set 'head' to temp.
If head is not NULL, you set temp's 'link' to head. Then you set head to temp. Then you loop and do it all over again.
So you end up with head pointing to temp, and temp->link pointing to temp... a circular list of exactly one node.
Try this instead:
int main()
{
int i = 0;
node *temp;
/* linked list logic to add the elements in the beginning */
while(i != 10)
{
/* First, allocate a new node */
temp = (node *)malloc(sizeof(node));
if(temp == NULL)
return -1; /* yikes */
/* now set its value */
temp->i = i++;
/* and link it into the list, at the beginning */
temp->link = head;
head = temp;
}
/* Now traverse the list, starting from 'head' */
temp = head;
while(temp != NULL)
{
/* save the current node in a temporary variable */
node *temp2 = temp;
/* and move 'temp' to point to the next node in the list */
temp = temp->link;
/* print the current node */
printf("\n The data is: %d\n", temp2->i);
/* and free the memory */
free(temp2);
}
return 0;
}

Resources