Thread: bsearch and struct **pointers

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    3

    Smile bsearch and struct **pointers

    Dear fellow coders,

    I've been having problems with this piece of code and I can't seem to figure out the cause. I'd really appreciate it if someone could point out why I'm getting errors here..

    Code:
    typedef struct {
       char *name; 
       unsigned long match_num; 
       unsigned long *match_support; 
       struct graphNode **link; 
    } graphNode;
    
    int node_compare(const void *a, const void *b) {
       return strcmp(((graphNode*)a)->name, ((graphNode*)b)->name);
    }
    
       graphNode **NODE_INDEX = (graphNode**) malloc(SHOTGUN_READ_NUM*sizeof(graphNode*));
    
    //SNIP
    
       qsort(NODE_INDEX, SHOTGUN_READ_NUM, sizeof(graphNode*), node_compare); // sort shotgun fragments by name
    
    // SNIP
    
       for (count=0; count<match_count_5; count++) { 
    	graphNode *a = malloc(sizeof(graphNode));
    	a->name = name_array_5[count]; // points a->name to a string in memory
    	graphNode *fromNode = bsearch(a, NODE_INDEX, SHOTGUN_READ_NUM, sizeof(graphNode*), node_compare);
    	free(a);
    
    //SNIP
    gdb shows that in node_compare(), the values pointed to by a->name and b->name are garbage, or sometimes out of bounds.

    Anyone?

  2. #2
    Registered User
    Join Date
    Apr 2004
    Posts
    25
    i'm a beginner in this.. but i'll make a contribution anyway and see what people say..

    in this line..
    graphNode *a = malloc(sizeof(graphNode));
    i noticed your missing your typecast?

    e.g.
    Code:
    main()
    {
       int* aPtr = NULL;
       
       aPtr = (int*)malloc(sizeof(int));
       *aPtr = 5;
    
       free(aPtr);
    }
    though looks like a and b are both void? i haven't done anything like this before. but seeing as they're both void i guess you don't need the typecast

  3. #3
    Registered User
    Join Date
    May 2005
    Posts
    3
    oops. I must've missed a few casts out.. It still doesn't work though, and I think it's more to do with the fact that the node_compare function isn't working right.

    Maybe I'm casting the args wrongly or something.. I'll work on it

    Thanks for the reply though!

    Quote Originally Posted by ahming
    i'm a beginner in this.. but i'll make a contribution anyway and see what people say..

    in this line..


    i noticed your missing your typecast?

    e.g.
    Code:
    main()
    {
       int* aPtr = NULL;
       
       aPtr = (int*)malloc(sizeof(int));
       *aPtr = 5;
    
       free(aPtr);
    }
    though looks like a and b are both void? i haven't done anything like this before. but seeing as they're both void i guess you don't need the typecast

  4. #4
    Me -=SoKrA=-'s Avatar
    Join Date
    Oct 2002
    Location
    Europe
    Posts
    448
    What is name_array_5 defined as?
    Why do you have void* in node_compare()? You don't need that. It would work just as good with graphNode* and it would be clearer.

    @ahming:
    You don't need a cast for malloc() because it returns void*. If you get a warning, you should #include <stdlib.h>.
    SoKrA-BTS "Judge not the program I made, but the one I've yet to code"
    I say what I say, I mean what I mean.
    IDE: emacs + make + gcc and proud of it.

  5. #5
    Registered User
    Join Date
    May 2005
    Posts
    3
    Quote Originally Posted by -=SoKrA=-
    What is name_array_5 defined as?
    Why do you have void* in node_compare()? You don't need that. It would work just as good with graphNode* and it would be clearer.
    name_array_5 is a char **, an array of strings basically.
    I made node_compare(void*, void*) because thats how it was defined in the stdlib documentation actually.. I didn't know you could just cast it directly

    Edit:

    It occured to me after posting that the key I pass to node_compare should probably be of the same type as NODE_INDEX elements.. doh.

    I went and created a dummy graphNode with the key I wanted and passed it in as a *graphNode. That still gives me some problems for some reason, so I went and tried **graphNode and modified node_compare as such. That works, but I have no idea why ? odd.

    But thanks for pointing out the obvious mistake I made there
    Last edited by reis_sg; 05-25-2005 at 08:28 AM.

  6. #6
    Me -=SoKrA=-'s Avatar
    Join Date
    Oct 2002
    Location
    Europe
    Posts
    448
    Quote Originally Posted by reis_sg
    I went and created a dummy graphNode with the key I wanted and passed it in as a *graphNode. That still gives me some problems for some reason, so I went and tried **graphNode and modified node_compare as such. That works, but I have no idea why ? odd.)
    Well, I don't know how you're calling node_compare, but if you're passing a graphNode**, it's not going to work, and precisely because you're doing all this casting, it gets hard to recognize.
    SoKrA-BTS "Judge not the program I made, but the one I've yet to code"
    I say what I say, I mean what I mean.
    IDE: emacs + make + gcc and proud of it.

  7. #7
    Registered User
    Join Date
    Apr 2004
    Posts
    25
    wow i think this is beyond me. i'm only starting to learn this stuff plus exam on it in two weeks sorry if i couldn't help

  8. #8
    Me -=SoKrA=-'s Avatar
    Join Date
    Oct 2002
    Location
    Europe
    Posts
    448
    Well, don't worry too much. You learn this with experience (not that I've that much).
    SoKrA-BTS "Judge not the program I made, but the one I've yet to code"
    I say what I say, I mean what I mean.
    IDE: emacs + make + gcc and proud of it.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,665
    If you have an array of T, then the pointers which your compare function receives have an effective type of T*.

    You're starting off with an array of graphNode*, so your compare function gets graphNode**

    Use temporary variables of the correct type, to save overly complex cast expressions.
    I think it should be something like this...
    Code:
    int node_compare(const void *a, const void *b) {
       graphNode **pa = a;
       graphNode **pb = b;
       return strcmp( (*pa)->name, (*pb)->name );
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Best way to handle incoming commands from a client.
    By ~Kyo~ in forum Game Programming
    Replies: 6
    Last Post: 07-26-2006, 12:24 PM
  2. bsearch( ) and qsort( ) not agreeing
    By Thumper333 in forum C Programming
    Replies: 1
    Last Post: 10-24-2004, 09:56 PM
  3. Problem Using bsearch
    By Zildjian in forum C Programming
    Replies: 4
    Last Post: 11-13-2003, 08:14 PM
  4. Filling an Array of Structures
    By Zildjian in forum C Programming
    Replies: 5
    Last Post: 11-12-2003, 05:54 PM
  5. Replies: 7
    Last Post: 04-13-2003, 10:53 PM