Hi all,
my C journey is going well so far, but I have hit a snag that I can't seem to get around. I posted on this board about a week ago asking for help with my linked list code (which was graciously answered) but now it seems to be throwing up memory issues. If I attempt to scan in 1000 items to the linked list, it throws up a segmentation fault, however, if I attempt to scan in the same items while debugging using GDB it runs with no problem. The research I did into the issue suggested that this is because GDB zeroes all initialized variables whereas a compiler will not, but changing my mallocs to callocs yielded no improvement.
Code:
#include "linked.h"
int main(int argc, char *argv[])
{
struct node_t* dict_head = NULL;
int search_key=0, list_size = 0;
if(argc < 2){
printf("Error: Command line arguments are not correct. Format should");
printf(" be: <program name> <input dictionary file>\n");
exit(EXIT_FAILURE);
}
/*We first create the linked list using the provided data file */
dict_head = insert_list(dict_head, argv, &list_size);
print_list(dict_head, list_size);
/*Now that we have created the linked list we are free to search through
it */
while(scanf("%d", &search_key) == 1){
search_list(dict_head, search_key);
}
return 0;
}
/* A basic function that takes a pointer to the head node, a pointer to
the first cmd line argument, and a pointer to the size variable as its
parameters, and uses this information to generate a linked list from
the input file */
struct node_t* insert_list(struct node_t* dict_head, char* argv[1],
int* list_size){
struct node_t* traversor;
struct node_t* newnode;
struct node_t* temp_node;
int insert_key = 0, insert_comparisons = 0;
char insert_word[256];
FILE* fp;
fp = fopen(argv[1], "r");
while(fscanf(fp,"%d %s\n", &insert_key, insert_word) == 2){
newnode = calloc(1,sizeof(struct node_t));
assert(newnode != NULL);
newnode->key = insert_key;
strcpy(newnode->word, insert_word);
newnode->next = NULL;
/*We need to check for the special case where the linked list
hasn't been initialised yet and thus we set the newnode
to be the headnode */
if(dict_head == NULL){
insert_comparisons += 1;
dict_head = newnode;
*list_size = *list_size + 1;
continue;
}
/* The second special case that we test for in which the newnode
needs to replace the head node. While it is simple to just switch
the two nodes around, we must also ensure that the previous head node
is now passed through the sorting portion of this function so that it
is inserted in the correct place */
if(newnode->key < dict_head->key){
insert_comparisons += 1;
temp_node = calloc(1,sizeof(struct node_t));
assert(temp_node != NULL);
temp_node = dict_head;
dict_head = newnode;
dict_head->next = temp_node->next;
newnode = temp_node;
}
traversor = dict_head;
while(traversor->next!= NULL){
if(traversor->next->key > newnode->key){break;}
insert_comparisons += 2;
traversor = traversor->next;
}
newnode->next = traversor->next;
traversor->next = newnode;
*list_size = *list_size + 1;
}
printf("%d Insertions %d\n", *list_size, insert_comparisons);
return dict_head;
}
/*A function that can be used to delete nodes from the linked list. While
it is never called from the main, the code works and has been tested
in special cases such as that where we want to delete the head node */
struct node_t* delete_list(struct node_t* dict_head, int del_key
, int* list_size){
struct node_t* delete_node = calloc(1,sizeof(struct node_t));
struct node_t* temp_node = calloc(1,sizeof(struct node_t));
if(dict_head->key == del_key){
*temp_node = *dict_head;
*dict_head = *temp_node->next;
free(temp_node);
*list_size = *list_size - 1;
return temp_node;
}
temp_node = dict_head;
while(temp_node->next->key < del_key){
if(temp_node->next == NULL){
printf("Word doesn't exist\n");
*list_size = *list_size - 1;
return dict_head;
}
temp_node = temp_node->next;
}
delete_node = temp_node->next;
if(delete_node->key != del_key){
printf("Word doesn't exist\n");
*list_size = *list_size - 1;
return dict_head;
}
/*Now we can assume that the correct key has been found and thus
we reassign the appropriate pointers and free the memory
that was being used by the word we have just deleted*/
temp_node->next = delete_node->next;
free(delete_node);
return dict_head;
}
void search_list(struct node_t* dict_head, int search_key){
struct node_t* search_traversor = calloc(1,sizeof(struct node_t));
int search_comparisons = 0;
search_traversor = dict_head;
while(search_traversor->key != search_key){
if(search_traversor->key > search_key|| search_traversor->next == NULL){
printf("%d NOT FOUND %d\n", search_key, search_comparisons);
return;
}
search_comparisons+=1;
search_traversor = search_traversor->next;
}
/*We can now assume that search_traversor is the node that we were
searching for and thus we print out how many comparisons were
required to find the word */
printf("%d %s %d\n", search_key, search_traversor->word
, search_comparisons);
return;
}
void print_list(struct node_t* dict_head, int list_size){
struct node_t* print_traversor = dict_head;
int i;
for(i = 0; i < list_size; i++){
if(print_traversor->next == NULL){
printf("%d %s\n",print_traversor->key, print_traversor->word);
break;
}
printf("%d %s\n",print_traversor->key, print_traversor->word);
print_traversor = print_traversor->next;
}
}
And here is the header file:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define WORDLEN 256
#define EXPECTED_INPUT 2
struct node_t{
int key;
char word[WORDLEN];
struct node_t *next;
};
struct node_t* sort_list(struct node_t* dict_head, int size);
struct node_t* insert_list(struct node_t* dict_head, char* argv[1], int* list_size);
struct node_t* delete_list(struct node_t* dict_head, int del_key, int* list_size);
void search_list(struct node_t* dict_head, int search_key);
void print_list(struct node_t* dict_head, int list_size);
This is slowly driving me mental, so any help would be greatly appreciated. If it helps, I tried running the program on a machine that was using GCC 3.4 and that caused a seg fault, but running it on a GCC 4.2 machine yielded no problems.
EDIT: Apparently an error in the input file can cause a segmentation fault, which is what was happening.