I tried to make a self-made program for lists. So, I created some basic stuff like creating the list, adding new nodes, showing them, and deleting all the existing nodes in the list.
However, when I put in my list more than 27 elements, it throws me a segmentation fault error while freeing the memory. By the way, when I add like 26 or smaller number of them, it works great. Maybe stack is overflowed or something like that, I really have no idea.
P.S don't tell me that I`m developing a bike, in this way, making something by myself first, I understand things better:)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct node{
struct node * next;
int value;
} node;
int addNode(int position,int value, node ** head,int * size){
int i = 2;
node * curNode = *head;
if(position > *size) return;
while(i <= *size){
if(position == 1){
node * adress = *head;
*head = (node*) malloc(sizeof(node*));
(*head)->next = adress;
(*head)->value = value;
break;
}
else if(i == position){
node * adress = curNode->next;
curNode->next = (node*) malloc(sizeof(node*));
curNode = curNode->next;
curNode->next = adress;
curNode->value = value;
break;
}
else{
curNode = curNode->next;
++i;
}
}
++(*size);
return;
}
void showList(node * head, int size){
int i; node * currentNode = head;
for(i = 0; i < size; ++i){
printf(" %d , next adress: %p |\n", currentNode->value, currentNode->next);
currentNode = currentNode->next;
}
printf("\n");
}
void cleanList(node * head, int size){
int i;
node * curNode = head; node * nextToDelete = NULL;
for(i = 0; i < size; ++i){
nextToDelete = curNode->next;
free(curNode);
curNode = nextToDelete;
}
}
int main() {
node * head = (node*) malloc(sizeof(node*)); //saving head adress to know where the list starts
head->value = 1; //set head value as "1"
int i, size;
node * currentNode = head; //pointer which points to a current node
for(i = 0; i < 5; ++i){
node * adress = (node*) malloc(sizeof(node*)); //variable which saves new node`s adress
currentNode->next = adress; //set this new nod`s adress to previous node`s "next" parametr
currentNode = adress; //set new node`s adress to a current node
currentNode->value = i+2; ///set value for this node
}
size = 6;
addNode(2, 15, &head, &size);
showList(head, size);
showList(head, size);
cleanList(head, size);
return 0;
}
You are allocating memory incorrectly.
Notice these lines:
*head = (node*) malloc(sizeof(node*));
and
curNode->next = (node*) malloc(sizeof(node*));
You are allocating memory for a pointer to struct node instead of the actual struct.
Notice the sizeof function - you pass it the wrong parameter!
Your structure contains an int and a pointer. Those are usually the same size.
But you only allocate memory for a pointer, so, you allocate half the structure.
This will cause you to call free on an invalid address at some point.
It is a miracle your program only crashed during free operation, it should have crashed much sooner.
Related
I am trying to create a list of 10 Nodes and assigning with the values 1 to 10 and printing them. I tried it with the following code, but I am ending up with segmentation fault.
I am very new to Linked Lists in C.
#include<stdio.h>
typedef struct Node
{
int data;
struct Node *next;
}Node_Struct;
int main(void)
{
int i =0;
Node_Struct* Node = NULL;
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
for (i = 1; i<=10; i++){
Node->data = i;
Node = Node->next;
}
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",Node->data);
Node = Node->next;
}
return 0;
}
As pointed by people in comments, you're only allocating memory to head node only. You need to allocate memory for each node you're trying to add int that for loop also. Moreover you're moving on the Node pointer forward at each iteration, so you won't be able to traverse list after insertion. Keep a track of both head and tail of the list. Do the following:
Maintain head and tail of linked list:
Node_Struct* headNode = NULL, *tailNode = NULL;
// head node
headNode = tailNode = (Node_Struct*)malloc(sizeof(Node_Struct));
Allocate memory at each iteration in the loop. It's your wish whether you want to keep something in head node or not. So change the code in for loop like this:
for (i = 1; i<=10; i++) {
Node_Struct* newNode = (Node_Struct *)malloc(sizeof(Node_Struct));
newNode->data = i;
newNode->next = NULL;
tailNode->next = newNode;
tailNode = newNode;
}
After this you can iterate your list by copying head value in some other variable:
Node_Struct *tmpNode = headNode;
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",tmpNode->data);
tmpNode = tmpNode->next;
}
You are not allocating memory for each added node.
If to use your loops then it is enough to make these minor changes
Node_Struct* Node = NULL;
Node_Struct **current = &Node;
for (i = 1; i <= 10; i++ ) {
*current = malloc(sizeof(Node_Struct));
(*current)->data = i;
(*current)->next = NULL;
current = &(*current)->next;
}
current = &Node;
for (i = 1; i <= 10; i++) {
printf("\n Node->data:%d", ( *current )->data);
current = &( *current )->next;
}
Take into account that you should free all allocated memory for the nodes before exiting the program.
You have allocated space for just a single node, yet you are trying to loop over a list of linked nodes by doing this:
for (i = 1; i<=10; i++){
Node->data = i;
Node = Node->next;
}
When you do this - Node = Node->next;, Node might point to anywhere. You might be pointing to memory you are not supposed to touch.
One thing to remember is never to let go of the handle to the head of the list. Keep a pointer to the head of the list by maintaining a copy.
Node = malloc(sizeof(Node_Struct));
Node_Struct *head = Node;
Allocate space for each node by using malloc(). Build up the list of nodes first. One way to do that is like this:
for (i = 1; i<=10; i++){
Node->next = malloc(sizeof (Node_Struct));
Node = Node->next;
}
Node->next = NULL // The last node should point to NULL
After that you could set all the data field of the nodes in another loop or, set them in the same loop while doing malloc(). As you already have the handle to the head of the list, you know where to start. Like so:
Node = head;
i = 0;
while (Node) {
Node->data = i++;
Node = Node->next;
}
First I am showing you where your mistakes are and below I have re-written you code to fix your problem. See my codes and compare with yours. Hope that will help you to learn data structure.
Let’s see you mistakes
#include<stdio.h>
typedef struct Node
{
int data;
struct Node *next;
}Node_Struct;
int main(void)
{
int i =0;
Node_Struct* Node = NULL;
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
for (i = 1; i<=10; i++){
Node->data = i;/* till here everything fine */
Node = Node->next; /* now you are pointing to nowhere */
/* in the next iteration of for loop Node->data = i will crash the application */
/* you could have done it like below
Node->next = (Node_Struct*)malloc(sizeof(Node_Struct));
Node = Node->next;
Node->data = i;
Node->next = NULL
but here you lost the address of first node so all gone*/
}
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",Node->data);
Node = Node->next;
}
return 0;
}
Now see my code below
int main(void)
{
int i =0;
Node_Struct *Node = NULL;
Node_Struct *p = NULL;
for (i = 1; i<=10; i++){
if ( Node == NULL )
{
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
Node->data = i;
Node->next = NULL;
p = Node; /* p is pointing to the first Node of the list */
}
else
{
p->next = (Node_Struct*)malloc(sizeof(Node_Struct));
p = p->next;
p->data = i;
p->next = NULL;
}
}
p = Node; /* now p is pointing to first node of the link list */
/* if you see above we always assign NULL to 'next' pointer so that the last node of the list pointing to NULL */
/* Therefore in the below while loop we are searching the list untill we reach the last node */
while( p != NULL )
{
printf("\n p->data:%d",p->data);
p = p->next;
}
return 0;
}
I'm getting assignment makes pointer from integer without a cast errors on lines 46 and 53, the two lines with double asterisks on either side, and for the life of me, I cannot figure out why. Linked lists are very new to me, I don't know how they work completely yet.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node_def
{
int data;
struct node_def *next;
};
typedef struct node_def node;
node *makeNode (int a);
node *insertFront(node *head,node *new);
void printList(node *head);
int numNodes = 0;
int main()
{
srand(time(0));
int r = rand() % 10000;
int i = 0;
node *head = NULL;
node *tmp = NULL;
printf("How many nodes? ", numNodes);
scanf("%d", numNodes);
printf("\n");
head = insertFront(head, tmp);
for(i = 0; i < numNodes; i++)
{
makeNode(r);
printList(head);
}
printf("\n");
return 0;
}
node *makeNode (int a)
{
node *new = malloc(sizeof(node));
**new = a;**
return new;
}
node *insertFront(node *head, node *new)
{
**new->data = head;**
new->next = new;
return 0;
}
void printList(node *head)
{
int j = 0;
for(j = 0; j < numNodes; ++j)
{
while (head != NULL)
{
printf(" %4d", head->data);
head = head->next;
}
if(j % 10 == 0)
printf("\n");
}
return;
}
new = a is meant to make new nodes and assign them a random number from 0 - 9999.
You try to assign r to new, but new is a struct.
You make a pointer to struct : node *new
What you want to do is assigning r to new->data, which is an int.
node *insertFront(node *head, node *new)
{
**new->data = head;** // ** is meaningless
new->next = new; // new is a reserved key word, don't use it this way
return 0;
}
What you try to do is to put a NULL pointer as the head of your list.
Just push element into it within your makeNode function.
insert like this :
void createNode(node *head)
{
Node *new_node = malloc(sizeof(Node*));
new_node->data = rand() % 100000;
new_node->next = NULL;
if(head == NULL)
head = new_node;
else if(head != NULL)
//Here you have to adapt your list, search (linked list crud functions)
}
You have a bad understanding about what pointers are.
Hope it helps bro
What this supposed to do is:
Create an array with 4 elements.
Print these 4 elements.
Copy array elements to a created linked list in copy fucntion.
Print linked list with print and traverse fuction.
I tried this and it compiles, but crashes after printing the array.
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ELEMENTS 4
struct node {
int data;
struct node *next;
};
struct node *head;
void insert(int x) {
struct node *temp = malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head != NULL)
temp->next = head;
head = temp;
}
void copy(struct node *head, int array[ELEMENTS], int n) {
//copying array elements and create linked list
struct node *temp = malloc(sizeof(struct node));
temp->data = array[0];
temp->next = NULL;
head = temp;
int i;
for (i = 1; i < n; i++) {
struct node *temp2 = malloc(sizeof(struct node));
temp->next = temp2;
temp2->data = array[i];
temp2->next = NULL;
temp = temp2;
}
}
void printlist() {
struct node*temp = head;
printf("List is : ");
while (temp->next != NULL) {
printf(" %d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
int *array = (int*)calloc(ELEMENTS , sizeof(int));
int i = 0;
for (i = 0; i < ELEMENTS; i++) {
printf("arrays = [%d] ", i);
scanf("%d", &array[i]);
}
for (i = 0; i < ELEMENTS; i++)
printf("array [%d] = %d \n", i, array[i]);
copy(head, array[ELEMENTS], ELEMENTS);
printlist();
getchar();
return(0);
}
How to fix it?
You dont need to pass head to the copy function because it is global and when you do you create a local pointer named head which gets destroyed as soon as function is over.
So copy should look like this
void copy(int array[ELEMENTS],int n) //copying array elements and create linked list
{
struct node*temp = malloc(sizeof(struct node));
temp->data=array[0];
temp->next=NULL;
head =temp;
int i;
for(i=1;i<n;i++)
{
struct node*temp2= malloc(sizeof(struct node));
temp->next= temp2;
temp2->data = array[i];
temp2->next = NULL;
temp=temp2;
}
}
Also while printing change while to
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp=temp->next;
}
When you call the function copy, you are passing "array[ELEMENTS]" as an argument, but you want to pass only "array". What you're passing is value after your array, which the copy function is trying to interpret as an address of an array it's actaully expecting.
Note that accessing a value that is not yours like this results in undefined behaviour and can actually make the system kill your application. But what probably happened after is there will be a 0 in the memory, which gets passed to the copy function and it then tries to access values at memory 0x0 to 0xF, which almost always results in segmentation fault, which as you experienced first hand, causes the program to stop working.
Bottom line, delete [ELEMENTS] at the line where you call the copy function and I believe the program should start working. I implore you though to do further research on pointers and passing them as function parameters.
(And since I cannot comment yet I will just put this in here, as Sniper stated, you don't have to pass reference to global variable, but he is wrong about the structure being destroyed at the end of the function. That would have been true, if it was created at stack, but you are allocating space for it at heap, which means it will stay there until you either free() it or the program ends.)
I have simple dimple answer:
#include<stdio.h>
#include<stdlib.h>
struct Node{
int current;
struct Node *next;
};
struct LinkedList{
struct Node *head;
};
int main(){
int i, data[5] = {10, 20, 30, 40, 50};
struct Node *node = malloc(sizeof(struct Node));
struct LinkedList *llist = malloc(sizeof(struct LinkedList));
node->current = data[0];
node->next = NULL;
llist-> head = node;
for(i = 1; i <= sizeof(data) / sizeof(data[0]) - 1; i++){
struct Node *new_node = malloc(sizeof(struct Node));
node->next = new_node;
new_node->current = data[i];
new_node->next = NULL;
node = new_node;
}
node = llist->head;
printf("llist: ");
while(node != NULL){
printf("%d->", node->current);
node = node->next;
}
return 0;
}
Ok so I have a hash table that I made in C. I'm using separate chaining (linked lists) to resolve collisions. I noticed that I can free the entire table IF there were no collisions and every item hashed to its own index. BUT if there is a collision and I have more than one value at an index, it is only able to free the first value and not the remaining values in that index. The program crashes when it tried to free the others at that index. I tried debugging it and I realized that those other values have been set to NULL, which I'm not sure why because when I'm inserting them to the table I'm using malloc. I know I'm missing something. If someone can help that would be super awesome, as I've been trying to solve this problem for several hours :/
Here's the code:
int symTabSearch(struct hashTable * h, char * label);
int insertToSymTab(struct hashTable * h, char * label, int locctr);
struct listNode
{
char * label;
int address;
struct listNode * next;
};
struct hashTableNode
{
int blockCount; //number of elements in a block
struct listNode * firstNode;
};
struct hashTable
{
int tableSize;
int count; //number of elements in the table
struct hashTableNode * table;
};
struct hashTable * createHashTable(int size)
{
struct hashTable * ht;
ht = (struct hashTable*)malloc(sizeof(struct hashTable));
if (!ht)
return NULL;
ht->tableSize = size;
ht->count = 0;
ht->table = (struct hashTableNode *)malloc(sizeof(struct hashTableNode) * ht->tableSize);
if (!ht->table)
{
printf("Memory error\n");
return NULL;
}
int i;
for (i = 0; i < ht->tableSize; i++)
{
ht->table[i].blockCount = 0;
ht->table[i].firstNode = NULL;
}
return ht;
}
/*hash function: adds up the ascii values of each
character, multiplies by a prime number (37) and mods the sum wih the table size*/
int hash(char * label, int tableSize)
{
int hashVal = 0;
size_t i;
for (i = 0; i < strlen(label); i++)
hashVal = 37 * hashVal + label[i];
hashVal %= tableSize;
if (hashVal < 0)
hashVal += tableSize;
return hashVal;
}
int symTabSearch(struct hashTable * h, char * label)
{
struct listNode * temp;
temp = h->table[hash(label, h->tableSize)].firstNode; //temp points to the first listNode in table[hashedIndex]
while (temp)
{
if (strcmp(temp->label, label) == 0)
return 1; //found
temp = temp->next; //go to next link
}
return 0; //not found
}
int insertToSymTab(struct hashTable * h, char * label, int locctr)
{
int index;
struct listNode * currentNode, *newNode;
index = hash(label, h->tableSize);
currentNode = h->table[index].firstNode;
newNode = (struct listNode *)malloc(sizeof(struct listNode));
newNode->label = (char *)malloc(sizeof(char) * 7); //allocates 7 chars to store label up to 6 chars long (0-5), last one is for the '\0'
if (!newNode) //if new node is null
{
printf("Error creating new node\n");
return 0;
}
strcpy(newNode->label, label);
newNode->address = locctr;
if (h->table[index].firstNode == NULL) //if first node at table index is empty
{
h->table[index].firstNode = newNode;
h->table[index].firstNode->next = NULL;
}
else
{ //firstNode was not empty, so chain newNode to the next empty node
while (currentNode != NULL) //go to next available node
currentNode = currentNode->next;
currentNode = newNode;
currentNode->next = NULL;
}
h->table[index].blockCount++;
h->count++;
return 1;
}
void freeHashTable(struct hashTable * h) //might not free memory properly, might crash too, test later
{
int i, j;
struct listNode * current, *temp;
char * tempStr;
if (!h) //make sure table even has memory to be freed
return;
for (i = 0; i < h->tableSize; i++)
{
current = h->table[i].firstNode;
for (j = 0; j < h->table[i].blockCount; j++)
{
temp = current;
tempStr = current->label;
current = current->next;
free(temp);
free(tempStr);
temp = NULL;
tempStr = NULL;
}
}
free(h->table);
h->table = NULL;
free(h);
h = NULL;
}
The problem is in the insertToSymTab function, when you attempt to append a node to the list.
The problem here is this loop:
while (currentNode != NULL) //go to next available node
currentNode = currentNode->next;
When that loop is done, you have passed the end of the list and the value of currentNode is NULL. Changing that pointer will not append the new node to the end of the list.
Instead you need to change your loop to e.g.
while (currentNode->next != NULL)
currentNode = currentNode->next;
Then when the loop is over, currentNode will instead be the last node currently in the list, and you append the new node by changing currentNode->next:
currentNode->next = newNode;
Don't forget to set newNode->next to NULL.
Your error is in insertToSymTab here:
while (currentNode != NULL) //go to next available node
currentNode = currentNode->next;
currentNode = newNode;
currentNode->next = NULL;
You set currentNode as currentNode->next (copying the pointer value) and then you set is as the newNode. But currentNode is not linked to the previous currentNode->next, it will just be a NULL pointer which you then assign to the newNode.
You either have to set currentNode->Next = newNode for the last node of the list or use a struct listnode ** pointer to achieve something similar to what I think you are trying here.
Edit: Joachim provided the answer more quickly
Hi i'm a new programmer for C, i get a segmentation fault in my linked list program, i was wondering if anyone could help me out. I've posted my code below... If you need furthure information I will post it. Thanks.
#include "list.h"
//+-------------------------------------------------------------
//+ CREATE NODE
//+
//+ Allocate memory for a node of type struct node and
//+ initialize it with d. Return a pointer to the new node.
//+-------------------------------------------------------------
struct node* createNode(int d){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode->item = d; //newNode's data is the value stored in 'd'
newNode->next = NULL; //sets the pointer to the next node to NULL
return newNode; //return the new node created
}
//+-------------------------------------------------------------
//+ INSERT HEAD NODE
//+
//+ Insert Node n in front of the head of the list, and set
//+ n to be the new head of the list.
//+-------------------------------------------------------------
void insertHead(struct node **headRef, struct node *n){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode->item = n->item; //newNode's data is assigned the value of the parameter node n''
newNode->next = *headRef; //since we are inserting the node at the head we set the next node to be the head reference
*headRef = newNode; //and then we assign the head reference to the new node created, thus, inserting the head node
}
//+-------------------------------------------------------------
//+ INSERT TAIL NODE
//+
//+ Insert Node n at the tail of the LinkedList.
//+-------------------------------------------------------------
void insertTail(struct node **headRef, struct node *n){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode = *headRef; //the new node is now the head reference
while(newNode->next != NULL) //while the next node is not equal NULL
newNode = newNode->next; //set the newNode to the next node (this finds the last node)
struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp
tmp->item = n->item; //the data of tmp is assigned the data of the parameter node 'n'
tmp->next = NULL; //the node following tmp is set to NULL
newNode->next = tmp; //tmp is now set to the next node, thus, becoming the last node i.e. the tail
}
//+-------------------------------------------------------------
//+ COUNT NODES IN LINKED LIST
//+
//+ Count the # of nodes that are part of the LinkedList.
//+-------------------------------------------------------------
int countNodes(struct node *headRef){
int counter = 0; //create a counter variable to store the number of nodes
struct node* current = headRef; //create a new node and assign it the reference to the head node
if(headRef = NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
while(current != NULL){ //while the current node is not NULL
counter++; //increment the counter
current = current->next; //and move on to the next node, thus, adding 1 to the counter with each node passed
}
return counter; //return the total number of nodes, stored in counter
}
//+-------------------------------------------------------------
//+ FIND NODE
//+
//+ Return the first node that has item = val, return NULL
//+ otherwise.
//+-------------------------------------------------------------
struct node* findNode(struct node *head, int val){
struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp
*tmp = *head; //node tmp is now referring to the head node of the list
while(tmp != NULL) //while the tmp node is not equal to NULL
{
if(tmp->item == val){ //if the data of the tmp node is equal to the value sent as parameter
return tmp; //return the tmp node
}else{
return NULL; //otherwise, return NULL
}
tmp = tmp->next; //set the tmp node to the next node in the list (traversing)
}
}
//+-------------------------------------------------------------
//+ DELETE NODE
//+
//+ Delete node n from the list and free memory allocated to n.
//+-------------------------------------------------------------
void deleteNode(struct node **headRef, struct node *n){
struct node* toBeDeletedNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called toBeDeletedNode
toBeDeletedNode = findNode(*headRef, n->item); //toBeDeletedNode is set to equal the node findNode() returns
//this node should be the node with its data = to the data of the parameter node n
free(toBeDeletedNode); //delete node toBeDeletedNode references and free the space allocated it
}
Here is the test file....
#include "list.h"
#include <assert.h>
#include <sys/types.h>
#include <stdio.h>
// create and insertHead
void test1()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
while(h<5)
insertHead(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == (4 - h) );
assert(h==5);
printf("HAHA");
}
// create and insertTail
void test2()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0, t=0;
while(h<5)
insertTail(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == h);
assert(h==5);
printf("HAHA");
}
// countNodes
void test3()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0, t=0;
while(h<50)
insertTail(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == h);
assert(countNodes(headRef) == 50);
}
// findNode
void test4()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
nptr = findNode(headRef, 1);
assert(nptr == NULL);
while(h<50)
insertTail(&headRef,createNode(h++));
nptr = findNode(headRef, 10);
assert(nptr != NULL);
assert (nptr->item = 10);
nptr = findNode(headRef, -10);
assert(nptr == NULL);
}
// deleteNode
void test5()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
while(h<5)
insertTail(&headRef,createNode(h++));
h = 0;
while(h<5) {
nptr = findNode(headRef, h);
assert(nptr != NULL);
deleteNode(&headRef, nptr);
assert(findNode(headRef, h) == NULL);
assert(countNodes(headRef) == (4 - h));
h++;
}
}
/*// sort
void test6()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
int d[5] = {1, 0, -1, 5, 100};
int ds[5] = {-1, 0, 1, 5, 100};
while(h<5)
insertTail(&headRef,createNode(d[h++]));
sort(&headRef);
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == ds[h]);
}*/
int main( int argc, char ** argv )
{
int testNum = 0;
if ( argc < 2 ) {
fprintf(stderr, "\n usage: %s test-num\n", argv[0]);
return 1;
}
testNum = atoi(argv[1]);
switch(testNum){
case 1:
test1();
break;
case 2:
test2();
break;
case 3:
test3();
break;
case 4:
test4();
break;
case 5:
test5();
break;
case 6:
//test6();
break;
default:
fprintf(stderr, "\n usage: %s 1 .. 8\n", argv[0]);
return 1;
}
return 0;
}
I don't know if this is the error, but this line is almost certainly wrong:
if(headRef = NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
and should be
if(headRef == NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
It's in countNodes().
There are quite a few issues here.
You are allocating new nodes when you should almost certainly not be, in insertHead, insertTail, findNode, and deleteNode. None of these functions should allocate anything (unless you genuinely want to copy the caller's nodes, which I doubt, in which case you should allocate in insertHead and insertTail, but not the other two, and you should use your own createNode function to do that). Ordinarily I would expect the insertHead function, for example, to simply take the passed-in node and insert it at the head of the list; it would not typically allocate a new node and copy the passed-in node's contents.
The insertTail function needs some work. It leaks a node each time and, I think, it crashes if you append to an empty list (the case in which the new tail is also the new head). Try something like:
void insertTail(struct node **head, struct node *n)
{
struct node **tmp = head;
while (*tmp != NULL)
{
tmp = &((*tmp)->next);
}
*tmp = n;
n->next = NULL;
}
In countNodes you have if (headRef = NULL) but that should be ==, not =.
There's no testing for alloc failures (though this is unlikely to be the cause of your segfault).
Personally, I would use calloc rather than malloc so that your new nodes have zeroed contents.
Your deleteNode function will seqfault if its call to findNode returns NULL.
I'd recommend adding in some asserts, for example:
void insertHead(struct node **head, struct node *n)
{
assert(head != NULL);
assert(n != NULL);
assert(n->next == NULL);
n->next = *head;
*head = n;
}
I'd recommend adding in some debugging aids, for example:
void printNodes(struct node *head)
{
int count = 0;
while (head != NULL)
{
printf("Item[%d] at %p = %d\n", ++count, head, head->item);
head = head->next;
}
}
struct node* tmp = malloc(sizeof(struct node));
where ever you have used this you are creating a blunder, malloc according to the ANSI spec returns the pointer to the allocated address, and you have to manually typecast it to the type that you wish it to be, the correct syntax is
struct node* tmp = (struct node*)malloc(sizeof(struct node));
you are also doing this
*tmp = *head;
you have to assign the pointers NOT the actual values contained at the corresponding memory locations, so write tmp=head because according to the standards, *p denotes the value of the location pointed by the pointer
also bad programming style, you are allocating memory in each and every function, you can create one pointer and allocate memory only once in the main function and then use it in your functions
a nice tips tutorial on segmentation error is here