Reputation: 23
I have written some code creating a singly linked list and then converting it to a dynamic array in C.
The code works just fine if I only create a global variable for the list header. If I want to create the list in my main function, however, I always get a segmentation fault.
The code below works just fine as soon as I create a global list variable instead and remove the list as parameter from all functions.
Can anyone tell me why this won't work if I want to pass the list as a parameter to the function and thus be able to create multiple lists?
#include <stdlib.h>
#include <stdio.h>
typedef struct NodeStruct* Node;
typedef struct NodeStruct {
Node next;
int val;
} NodeStruct;
typedef Node List;
Node newNode(int x){
Node n = (Node)malloc(sizeof(NodeStruct));
if(n!=NULL){
n->val = x;
n->next = NULL;
return n;
}
else{
printf("ERROR: Could not allocate memory!\n");
}
exit(1);
}
void prepend(List l, Node node){
if (l == NULL) l = node;
else{
node->next = l;
l = node;
}
}
void printList(List l){
if(l!=NULL){
Node n = l;
while(n->next != NULL){
printf("%d, ", n->val);
n = n->next;
}
printf("%d\n", n->val);
}
else{
printf("ERROR: List empty!\n");
}
}
/*=============================*/
int* arrOf(List l){
if(l==NULL){
printf("ERROR: List empty\n");
exit(1);
}
int size = 0;
Node n = l;
while(n!=NULL){
size++;
n = n->next;
}
int* arr = (int*)malloc((size+1)*sizeof(int));
n = l;
int i = 0;
arr[i++] = size;
while(n != NULL){
arr[i++] = n->val;
n = n->next;
}
printf("Returning Array\n");
return arr;
}
int main(int argc, char *argv[]){
List l;
prepend(l, newNode(5));
prepend(l, newNode(6));
prepend(l, newNode(7));
prepend(l, newNode(8));
prepend(l, newNode(9));
prepend(l, newNode(4));
printList(l);
printf("\n===========================================\n");
int* arr = arrOf(l);
for(int i = 0; i < 10; ++i){
printf("%d, ", arr[i]);
}
return 0;
}
Upvotes: 1
Views: 123
Reputation: 311048
This function
void prepend(List l, Node node){
if (l == NULL) l = node;
else{
node->next = l;
l = node;
}
}
deals with a copy of the value of the pointer l
declared in main
List l;
that moreover was not initialized.
So changing of the copy in these statements within the function
if (l == NULL) l = node;
//...
l = node;
does not influence on the original value of the pointer declared in main.
You have to write at least like
void prepend(List *l, Node node){
node->next = *l;
*l = node;
}
and in main
List l = NULL;
The function can be called like
prepend( &l, newNode(5) );
That is the pointer to the head node must be passed to the function by reference.
Also you need to free all the dynamically allocated memory for the list and the array.
Upvotes: 1
Reputation: 1931
When you initialize List l
in main
, you are not assigning a default value. It is stored on the stack and not initialized. This means the value is undefined and not necessarily null.
When you are creating List l
globally, the variable is stored in the bss segment and initialized with null.
Change your declaration of List l
to:
List l = NULL;
Upvotes: 2