ENBYSS
ENBYSS

Reputation: 929

C - A line of code is changing the address of a struct

I have a major issue that is happening to my code, that I've been trying to fix for hours now.

The code below is the one relevant to the issue that I am having...

The method addBucket:

void addBucket(SPACE * hashmap,char * tempvalue, char * tempkey){
    printf("BEGINNING OF FUNC...\n");

    void *prevadd = hashmap[0];
    char *value = varString(tempvalue);
    char *key = varString(tempkey);
    void *aftadd = hashmap[0];

    printf("BUCKET %s - %s\n",value,key);

    BUCKET *newBucket = malloc(sizeof(BUCKET *));
    fillBucket(value,key,newBucket);
    int hash = hashFunc(key);

    printf("FILL, FULFILLED\n");

    if(!hashmap[hash]){
        hashmap[hash] = malloc(sizeof(BASE*));
        hashmap[hash]->first = NULL;
    }

    ITEM *location;
    location = hashmap[hash]->first;

    //This creates a new item in the list, if there isn't any.
    //It does this by initialising the base, called box.
    if(!location){
        hashmap[hash]->first = (ITEM *) calloc(1,sizeof(ITEM *));
        hashmap[hash]->first->next = NULL;
        hashmap[hash]->first->prev = NULL;
        hashmap[hash]->first->data = newBucket;
    }

        //This instead adds a new item to the list.
    else{
        //This loop reaches the last ITEM in the linked list itself
        while(location->next){
            location = location->next;
        }

        //This initialises the newItem that will be added
        ITEM *newItem = (ITEM *) calloc(1,sizeof(ITEM));
        newItem->next = NULL;
        newItem->data = newBucket;
        newItem->prev = location;
        location->next = newItem;
    }
}

The declared structs that are used:

//Declares a struct called BUCKET.
//Serves as the bucket of the hash table.
typedef struct bucket{
    char * value; //The value inputted.
    char * key; //The key to be hashed.
}BUCKET;

//Declares a struct called ITEM.
//Holds the bucket, as well as the address to the next bucket.
//It also holds the address to the previous bucket.
typedef struct item{
    struct bucket * data;
    struct item * next;
    struct item * prev;
}ITEM;


//Declares a struct called BASE.
//Serves as the base node for the linked lists.
//The amount of initialised linked lists is the same as the amount of bases.
typedef struct base{
    struct item * first;
}BASE;

//Declares a struct of an array of BASES, meaning linked lists.
//Essentially defines the size of the hashspace.
typedef BASE *SPACE;

...And the method expandHashspace(); :

//Makes the size of the entire hashspace larger.
//Only takes a value larger than the current size due to possible data loss.
SPACE* expandHashspace(SPACE *hashmap, int newSize){
    if(newSize>100 || newSize<hashSpaceSize){
        printf("Exiting...\n");
        return NULL;
    }
    else {
        SPACE *nw = NULL;
        nw = realloc(hashmap, sizeof(SPACE *) * newSize);
        hashmap = nw;
        hashSpaceSize = newSize;
        return hashmap;
    }
}

Here's also the initHashmap() method:

SPACE* hashmapInit(SPACE *hashmap){
    hashmap = calloc(5, sizeof(SPACE *));
    hashSpaceSize = 5;
    return hashmap;
}

What I am doing here is initialising the hashmap, adding three buckets, expanding the hashmap, then adding three more buckets. Here's the order in more simple terms:

initHashmap();
addBucket(...); x3
expandHashmap();
addBucket(...); x3

However, on that last part, as soon as I run addBucket once, I get a SIGSEGV error. Checking through debugging, I realised something that was off.

Do you see the variables *prevadd and *aftadd? I added them while debugging to see what was happening to the address of hashmap[0]. Here is a picture of my results:

Can you see the problem?

As you can see there, the address of hashmap[0] varied wildly during those two char * lines. Specifically, the change of address happens on the char *value line.

Please go easy on me, as I've just started learning C 3 months ago, and I am still incredibly unaccustomed to memory allocation. If the error is obvious, please point it out, and if I have some problem with the way that I am allocating memory, or freeing it, I am more than happy to hear them (my code has a pretty major heisenbug that I cannot fix for the life of me, but that's beside the point).

Thank you in advance... Sorry for all the recent questions.

update : forgot to add varString();...

char* varString(const char *origString){
    size_t i;
    for(i = 0;origString[(int)i]!='\0';i++){}
    if(origString[i-1]=='\n') i-=2;
    char *newString = malloc(i);
    for(int j = 0; j <= i; j++){
        newString[j] = origString[j];
    }
    newString[i+1] = '\0';
    return newString;
}

Upvotes: 0

Views: 76

Answers (1)

lockcmpxchg8b
lockcmpxchg8b

Reputation: 2303

This is not an answer, but it needed more formatting than would fit in a comment:

Note that you are writing "Value No. 1"

Note the value of aftadd is 0x756c6156

In memory, assuming a little-endian machine, the layout of the number in aftadd would be:

0x56 0x61 0x6c 0x75

In ASCII these would be:

'V' 'a' 'l' 'u'

Hint hint.

Upvotes: 5

Related Questions