Why does uint64_t value change when it is being assigned into unit64_t** array element?

96 views Asked by At

I am trying to simulate a memory manager in C language. I need help solving a problem with assigning uint64_t values into an uint64_t** array elements.

After writing the code, I tested it by trying to write several values.

ex:- 0x2222222222222222, 0x33, 0x11111111 ....

This is my complete code.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

struct Memory{
    int hashtablesize;
    uint32_t **hashtable; // The array address in use 
    uint64_t **values; // Stored values


    void (*write)(uint32_t *address, struct Data *data, struct Memory *mem);

    void (*read)(uint32_t *address, struct Data *data, struct Memory *mem);

    int (*cell_index)(uint32_t *address, struct Memory *mem);

    void (*extend_hashtable)(struct Memory *mem);

    void (*dump)(struct Memory *mem);

};

struct Data{
    enum Type {UINT8,UINT16,UINT32,UINT64} type;
    uint64_t* value;
};


void write(uint32_t *address, struct Data *data, struct Memory *mem){

    int cell_index = mem->cell_index(address,mem);

    if(data->type==UINT8){
        uint64_t value = *((uint64_t*)data->value) & 0x00000000000000FF;
        mem->values[cell_index]=value;
    }
    if(data->type==UINT16){
        uint64_t value = *((uint64_t*)data->value) & 0x000000000000FFFF;
        mem->values[cell_index]=value;
    }
    if(data->type==UINT32){
        uint64_t value = *((uint64_t*)data->value) & 0x00000000FFFFFFFF;
        mem->values[cell_index]=value;
    }
    if(data->type==UINT64){
        uint64_t value = *((uint64_t*)data->value) & 0xFFFFFFFFFFFFFFFF;
        mem->values[cell_index]=value;
    }
    
    mem->hashtable[cell_index]=*address;
}

//void read(uint32_t *address, struct Data *data, struct Memory *mem){

    // To be implemented

//}


// Return the index of the given address from **hashtable
int cell_index(uint32_t *address, struct Memory *mem){
    int hashtablesize = mem->hashtablesize;

    for(int i;i<hashtablesize;i++){
        if(mem->hashtable[i]==*address){
            return i;
        }
    }
    mem->extend_hashtable(mem);

    return mem->hashtablesize-1;
}


// This function dynamically allocate memory for new memory addresses
void extend_hashtable(struct Memory *mem){
    int hashtablesize = mem->hashtablesize;

    uint32_t **new_hashtable = (uint32_t*)malloc(sizeof(uint32_t*)*(hashtablesize+1));
    uint64_t **new_values = (uint64_t*)malloc(sizeof(uint64_t*)*(hashtablesize+1));

    memset(new_hashtable, 0, (hashtablesize+1) * sizeof(uint32_t*));
    memset(new_values, 0, (hashtablesize+1) * sizeof(uint64_t*));

    for(int i;i<hashtablesize;i++){
        new_hashtable[i] = (uint32_t*)malloc(sizeof(uint32_t));
        memset(new_hashtable[i], 0, sizeof(uint32_t));
        new_hashtable[i] = mem->hashtable[i];
    }

    for(int i;i<hashtablesize;i++){
        new_values[i] = (uint64_t*)malloc(sizeof(uint64_t));
        memset(new_values[i], 0, sizeof(uint64_t));
        new_values[i] = mem->values[i];
    }

    mem->hashtable = new_hashtable;
    mem->hashtablesize+=1;
    mem->values = new_values;

}


// Print out the addresses and store values
void dump(struct Memory *mem){
    int hashtablesize = mem->hashtablesize;

    for(int i;i<hashtablesize;i++){
        printf("Memory Address: %x, \t Value: %u\n",mem->hashtable[i],mem->values[i]);
    }
    printf("Memory dump success\n");
}

In the dump method, the used addresses and the stored values will be printed.

I tried to write the following value in order. Please consider that I provided Data objects (structs) with the correct type.

0x11111111 #(type : UINT32)
0x2222222222222222  #(type : UINT64)
0x33  #(type : UINT8)

I expected the following output.

Memory Address: a,       Value: 11111111
Memory Address: 14,      Value: 2222222222222222
Memory Address: 1e,      Value: 33
Memory dump success

But I got this.

Memory Address: a,       Value: f7ff2ba011111111
Memory Address: 14,      Value: f7ff2ba022222222
Memory Address: 1e,      Value: f7ff2ba000000033
Memory dump success

The first 32 bits are either being overwritten by random values or are not being replaced by the new values I want to write.

I know this is a problem with pointer variables, but can't figure out how to fix this

I tried to figure out if there was any problem with casting by printing the result of casting. That works fine. So the problem is with assigning them into the values in the Memory struct.

This is the code for testing.

#include <stdint.h>
#include <stdio.h>
#include "memory.h"


struct Memory memobj;
struct Memory *mem = &memobj;


int main(){

    uint32_t *addresses[3];
    uint32_t a1=10,a2=20,a3=30;
    addresses[0] = &a1;
    addresses[1] = &a2;
    addresses[2] = &a3;

    uint64_t *values_to_write[3];
    struct Data d1,d2,d3;

    d1.type=UINT32;
    d1.value = malloc(sizeof(uint32_t));
    *(uint32_t*)d1.value=0x11111111;

    d2.type=UINT64;
    d2.value = malloc(sizeof(uint64_t));
    *(uint64_t*)d2.value = 0x222222222222222;

    d3.type=UINT8;
    d3.value = malloc(sizeof(uint8_t));
    *(uint8_t*)d3.value = 0x33;



    values_to_write[0] = &d1;
    values_to_write[1] = &d2;
    values_to_write[2] = &d3;

    mem->hashtable = (uint32_t**)malloc(sizeof(uint32_t));
    mem->values = (uint64_t**)malloc(sizeof(uint64_t));
    memset(mem->hashtable,0,sizeof(uint32_t)*1);
    memset(mem->values,0,sizeof(uint64_t)*1);
    mem->hashtablesize=0;

    mem->cell_index = cell_index;
    mem->dump = dump;
    mem->extend_hashtable = extend_hashtable;
    mem->read = read;
    mem->write = write;

    for(int i=0;i<3;i++){
        mem->write(addresses[i],values_to_write[i],mem);
    }

    mem->dump(mem);
    return 0;
}

Can someone tell me how to fix this or where can I find a solution for this?

0

There are 0 answers