Thread: strcmp segfault ?

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    58

    strcmp segfault ?

    Im having trouble finding what my problem is..

    Im writing a binary tree library and when I run this test program: (cannot be changed)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "bintree.h"
    
    void print_name(char *key, void *value){
       printf("&#37;s\n", key);
    }
    
    main(int argc, char *argv[]) {
      if (argc <= 1) {
        fprintf(stderr, "usage: bst_test name1 name2 ... namek\n");
        exit(1);
      }
      void *tree = create_tree();
      int i;
    
      // test inserts
      for (i = 1; i < argc; i++) {
         tree_insert(strdup(argv[i]), (void *)1, tree);
      }
    
      // test print tree
      print_tree(tree, print_name);
    
      // test finds
      for (i = 0; i < argc; i++) {
        if (tree_find(argv[i], tree) == 0)
          printf("%s not in data set\n", argv[i]);
      }
    }
    I get these errors:

    Code:
    (gdb) bt
    #0  0xb7edfd2a in strcmp () from /lib/tls/i686/cmov/libc.so.6
    #1  0x0804853e in tree_insert (key=0x804a030 "name", value=0x1,
        tree=0x804a008) at bintree.c:33
    #2  0x0804878d in main (argc=3, argv=0xbfe13134) at test.c:22

    Here is the library im writing:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    
    typedef struct _node{
        struct _node *children;
        struct _node *next;
        char *name;
        int space;
        int x; //x coordinate
        int y; //y coordinate
    } NODE;
    
    typedef struct _bnode{
        char *name;
        struct _node family_node;
        struct _bnode *left;
        struct _bnode *right;
    } BNODE;
    
    BNODE *tree_insert(char *key, void *value, void *tree){
        BNODE *root = (BNODE *)tree;
        if(root == 0){
            root = (BNODE *)malloc(sizeof(BNODE));
            if(root != NULL)
            {
                root->name = strdup(key);
                root->left = NULL;
                root->right = NULL;
            }
        }else{
            if(strcmp(key, root->name) < 0){   <--- line 33
                root->left = tree_insert(key, value, root->left);
            }else if(strcmp(key, root->name) > 0){
                root->right = tree_insert(key, value, root->right);
            }else if(strcmp(key, root->name) == 0){
    	    root->name = strdup(key);
            }
        }
    
        return root;
    }
    
    
    BNODE *tree_find(char *key, void *tree){
        BNODE *root = (BNODE *)tree;
        if(root == 0){
            return 0;
        }
        if(strcmp(key, root->name) < 0){
            return tree_find(key, root->left);
        }else if(strcmp(key, root->name) > 0){
            return tree_find(key, root->right);
        }else{
            return root;
        }
    }
    
    
    void *create_tree(){
        BNODE *new_tree = (BNODE *)malloc(sizeof(BNODE));
        new_tree->left = NULL;
        new_tree->right = NULL;
    
    }
    
    void print_tree(void *tree, void(*print_fct)(char *key, void *value)){
        BNODE *current = (BNODE *)tree;
    
        if(current == NULL || print_fct == NULL){
            return;
        }else{
            print_tree(current->left, print_fct);
    
            print_fct(current->name, (void *)current->family_node.space);
    
            print_tree(current->right, print_fct);
        }
    
    }

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In the else case, you KNOW root is NULL; that's the only way you can get there. And yet you try to follow root->name anyway? Why? Looking at it, the != case should be the == case, and vice versa.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
      void *tree = create_tree();
    ...
    void *create_tree(){
        BNODE *new_tree = (BNODE *)malloc(sizeof(BNODE));
        new_tree->left = NULL;
        new_tree->right = NULL;
    
    }
    What is the return value of create_tree?


    If this is C, then both of these casts are unnecessary (as well as the one in create_tree):
    Code:
        BNODE *root = (BNODE *)tree;
        if(root == 0){
            root = (BNODE *)malloc(sizeof(BNODE));
    If you are using C++ to compiler, then you should really rename your files to .c instead of .cpp.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by tabstop View Post
    In the else case, you KNOW root is NULL; that's the only way you can get there. And yet you try to follow root->name anyway? Why? Looking at it, the != case should be the == case, and vice versa.
    Not so. The else you are referring to is for the FIRST if, that tests if root == 0. The inner if is checking if the malloc worked, and if it did it fills in the tree - there probably should be a "else fatal_error("No memory");" or some such in that if-clause.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Posts
    58
    Quote Originally Posted by matsp View Post
    Code:
      void *tree = create_tree();
    ...
    void *create_tree(){
        BNODE *new_tree = (BNODE *)malloc(sizeof(BNODE));
        new_tree->left = NULL;
        new_tree->right = NULL;
    
    }
    What is the return value of create_tree?
    I added

    return new_tree;

    If this is C, then both of these casts are unnecessary (as well as the one in create_tree):
    Code:
        BNODE *root = (BNODE *)tree;
        if(root == 0){
            root = (BNODE *)malloc(sizeof(BNODE));
    So what should I put instead?
    Should I just declare the variable and not malloc it?

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Mats is referring to that you should remove the casts, but it is not really necessary. The only problem is that it can hide some errors. But if you have a good compiler (like Visual C++), it will warn about it anyway.
    There is nothing wrong with casts in the assignments, however (from void* to T*). You don't need it, but if you feel like having it, there's nothing wrong with that either.
    I like having casts, myself.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Posts
    58
    Quote Originally Posted by Elysia View Post
    Mats is referring to that you should remove the casts, but it is not really necessary. The only problem is that it can hide some errors. But if you have a good compiler (like Visual C++), it will warn about it anyway.
    There is nothing wrong with casts in the assignments, however (from void* to T*). You don't need it, but if you feel like having it, there's nothing wrong with that either.
    I like having casts, myself.

    So what do i do to fix my segfault........

    PLease help me...

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Despite your returning a node from create_tree() you are not initializing the name pointer as in
    Code:
    void *create_tree(){ /* root->name is not initialized in this routine */
        BNODE *new_tree = (BNODE *)malloc(sizeof(BNODE));
        new_tree->left = NULL;
        new_tree->right = NULL;
    
    }
    you allocated the root node but forgot to initialize its element root->name so what do you think will happen to strcmp()?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Fucntion returns -1, Why?
    By Taper in forum C Programming
    Replies: 16
    Last Post: 12-08-2008, 06:30 PM
  2. malloc() resulting in a SegFault?!
    By cipher82 in forum C++ Programming
    Replies: 21
    Last Post: 09-18-2008, 11:24 AM
  3. help with switch statement
    By agentsmith in forum C Programming
    Replies: 11
    Last Post: 08-26-2008, 04:02 PM
  4. help with strcmp
    By blork_98 in forum C Programming
    Replies: 8
    Last Post: 02-21-2006, 08:23 PM
  5. strcmp
    By kryonik in forum C Programming
    Replies: 9
    Last Post: 10-11-2005, 11:04 AM