Thread: Discrepancies between standard run-time and GDB

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    5

    Discrepancies between standard run-time and GDB (FIXED)

    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.
    Last edited by James McLaren; 09-04-2013 at 07:00 AM.

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    your code logic in lines 79-85 is wrong
    moreover the continue is missing in this branch

    your delete_list and search_list should not allocate any memory - so they obviously also have some logic flows...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Aug 2013
    Posts
    5
    Oh true, completely missed that. Thanks!

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Your "second special case" for inserting a node is broken. It munges the first couple of nodes in the list.

    When you're deleting nodes from a list, it should not be necessary to allocate anything.

    Because of those sorts of things, I suspect you will find that ANY of your code which traverses the list will go astray.

    As to why it doesn't break with gdb .... compiling without optimisation, and stepping through with a debugger, typically cause memory being used by your program to be reorganised. The result of that will be changing the symptoms that result from pointer molestation (i.e. when one of your functions does untoward things with a pointer).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 04-17-2013, 11:32 PM
  2. Time-of-Day Functionality WITHOUT Standard Libs
    By JDGATX in forum C Programming
    Replies: 6
    Last Post: 03-11-2008, 09:43 AM
  3. Does C++ have any standard implementation for time/date?
    By indigo0086 in forum C++ Programming
    Replies: 4
    Last Post: 01-12-2007, 01:05 PM
  4. standard time, help.
    By antex in forum C++ Programming
    Replies: 3
    Last Post: 10-19-2004, 03:00 PM
  5. standard language, standard compiler?
    By doubleanti in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 09-03-2001, 04:21 AM

Tags for this Thread