简体   繁体   中英

UTHash Segmentation fault when modifying example using struct as key

I'm trying to use UTHash by modifying the Standard Key Types, Struct Keys example for my purposes seen in the following link:

https://troydhanson.github.io/uthash/userguide.html#_structure_keys

Here is the my modified code (stripped down to show where I've isolated the problem to)

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "uthash.h"

typedef struct StateKey
{
    // array of bools that gives the instances that are present.
    bool *instancesAtNode_BoolArray;

} t_StateKey;


typedef struct State
{
    // State Key.  
    t_StateKey stateKey_StateKey;

    // probability of being in the given state
    double p;

    // UTHash handle array used for hashing 
    UT_hash_handle hh;

} t_State;

int main(int argc, char *argv[]) {

    double a = .80;
    double b = .2;     
    double c = .1;     
    //double d = .7;    

    t_State *state, *stateHead, *toFind = NULL;
    state = (t_State *) malloc(sizeof(t_State));
    memset(state, 0, sizeof(t_State));
    state->stateKey_StateKey.instancesAtNode_BoolArray = NULL;
    state->p = 1;

    HASH_ADD(hh, stateHead, stateKey_StateKey, sizeof(t_StateKey), state);

    return 0;
}

Notice that in main I have commented out the variable d. Running the code as it is below gives no problems, but the moment that I uncomment d the code throws a segmentation fault. This to me indicates that there is so kind of out of bounds error happening that the OS is picking up on only when the code is has a particular size/organization (which is why commenting out a seemingly unrelated variable prevents the bug).

I'm at a loss as to what I'm doing wrong since I'm following the example as its given as far as I can tell. Looking at Valgrind I get the following

==94553== Conditional jump or move depends on uninitialised value(s)
==94553==    at 0x10000195F: main (testNewMcUniverseMain.c:40)
==94553==  Uninitialised value was created by a stack allocation
==94553==    at 0x7FFF5FC01036: _dyld_start (in /usr/lib/dyld)
==94553== 
==94553== Use of uninitialised value of size 8
==94553==    at 0x100001A9F: main (testNewMcUniverseMain.c:40)
==94553==  Uninitialised value was created by a stack allocation
==94553==    at 0x7FFF5FC01036: _dyld_start (in /usr/lib/dyld)
==94553== 
==94553== Use of uninitialised value of size 8
==94553==    at 0x100001ABF: main (testNewMcUniverseMain.c:40)
==94553==  Uninitialised value was created by a stack allocation
==94553==    at 0x7FFF5FC01036: _dyld_start (in /usr/lib/dyld)
==94553== 
==94553== Use of uninitialised value of size 8
==94553==    at 0x100001ACB: main (testNewMcUniverseMain.c:40)
==94553==  Uninitialised value was created by a stack allocation
==94553==    at 0x7FFF5FC01036: _dyld_start (in /usr/lib/dyld)
==94553== 
==94553== Use of uninitialised value of size 8
==94553==    at 0x100001AE6: main (testNewMcUniverseMain.c:40)
==94553==  Uninitialised value was created by a stack allocation
==94553==    at 0x7FFF5FC01036: _dyld_start (in /usr/lib/dyld)
==94553== 
==94553== Invalid write of size 8
==94553==    at 0x100001AEE: main (testNewMcUniverseMain.c:40)
==94553==  Address 0x5400313d524f4c5f is not stack'd, malloc'd or 
(recently) free'd
==94553== 
==94553== Signal 11 being dropped from thread 0's queue
==94553== Signal 11 being dropped from thread 0's queue
==94553== Signal 11 being dropped from thread 0's queue
==94553== Signal 11 being dropped from thread 0's queue

(Repeats this line forever, I had to kill the terminal)

Am I doing something wrong or this an issue with UTHash? If it is UTHash, what would be another hash table library that I could use for C (Not C++)?

For Simplicity I have copied the UTHash Example code from the source I cited below

#include <stdlib.h>
#include <stdio.h>
#include "uthash.h"

typedef struct {
  char a;
  int b;
}     record_key_t;

typedef struct {
    record_key_t key;
    /* ... other data ... */
    UT_hash_handle hh;
} record_t;

int main(int argc, char *argv[]) {
    record_t l, *p, *r, *tmp, *records = NULL;

    r = (record_t *)malloc(sizeof *r);
    memset(r, 0, sizeof *r);
    r->key.a = 'a';
    r->key.b = 1;
    HASH_ADD(hh, records, key, sizeof(record_key_t), r);

    memset(&l, 0, sizeof(record_t));
    l.key.a = 'a';
    l.key.b = 1;
    HASH_FIND(hh, records, &l.key, sizeof(record_key_t), p);

    if (p) printf("found %c %d\n", p->key.a, p->key.b);

    HASH_ITER(hh, records, p, tmp) {
       HASH_DEL(records, p);
       free(p);
    }
    return 0;
}

I had a stupid.

From the example

record_t l, *p, *r, *tmp, *records = NULL;

will initialize ONLY records to be null. Since UTHash requires the "head" (in this case records) to be initialized to null this example works. In my example the head is "stateHead" and not initialized to null. For some reason I decided that

t_State *state, *stateHead, *toFind = NULL;

set all of these pointers to null (not how C works).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM