0

I use debugger in xcode go through my code line by line and finally found where it breaks, because c->sets[10] is NULL, however I do not know the causes.

I declared three structs, line, set and cache.

typedef  struct{
    int access_time;
    int tag;
    int valid;
}line;
typedef  struct{
    line *line;
    int empty;
    int insert;

}set;

typedef  struct{
    int set_num;
    int line_num;
    set* sets;
}cache;

I init a cache, s is 4, b is 4, and E is 1, which means sets in cache struct is an array with size of 16, each set has one line.

cache* init(int s, int b, int E){
cache* c =malloc(sizeof(cache)) ;
assert(c!= NULL);
//cache* c;
c->set_num = (1<<s);
c->line_num = E;
c->sets = (set*)malloc(c->set_num*sizeof(c->sets));
assert(c->sets != NULL);
for (int i=0;i<(1<<s);i++){
    c->sets[i].empty=E;
    c->sets[i].line=(line*)malloc(E* sizeof(*c->sets[i].line));
    c->sets[i].insert=0;

    assert(NULL!=c->sets[i].line);
    if (!c->sets[i].line){
        printf("null here");
    }else{
        for (int j=0; j<E;j++){

             c->sets[i].line[j].access_time = 0 ;
            c->sets[i].line[j].valid = 0;
            c->sets[i].line[j].tag = 0;

        }
    }
}
return c;

}

I have following code, set is 2, tag is 23456, c is already initiated with value in it.

void do_S(cache* c, int set, int tag){


  int i= c->sets[10].line[0].valid;
for(int i=0; i <E;i++ ){

    if (c->sets[set].line[i].valid==1){
        if ( c->sets[set].line[i].tag ==tag )
        {
            hit_count++;
            c->sets[set].line[i].access_time++;
            printf("hit ");
            return;
        }
        }

    }
l10 = c->sets[10].line;
miss_count++;
printf("miss ");
if (c->sets[set].empty==0){
    eviction_count++;
    printf("evict ");
    c->sets[set].line[c->sets[set].insert].tag=tag;
    c->sets[set].line[c->sets[set].insert].valid = 1;
    update_insert(c, set);
}else{
    l10 = c->sets[10].line;
    c->sets[set].empty--;
    l10 = c->sets[10].line; //c->sets[10].line still contains correct value and address is 0x1001043e0  
    c->sets[set].line[c->sets[set].insert].tag = tag;
    c->sets[set].line[c->sets[set].insert].valid = 1;
    l10 = c->sets[10].line; //c->sets[10].line still contains correct value and address is 0x1001043e0

    //update_insert(c,set);
    l10 = c->sets[10].line; //c->sets[10].line becomes NULL address change to 0x0000600a001043e0.


}

}

The code did not do anything there, but address is changed and c->sets[10].line turns to null.

1 Answer 1

3

This allocation is incorrect:

c->sets = (set*)malloc(c->set_num*sizeof(c->sets));

It allocates space for c->set_num pointers (to sets), but what you want is space for c->set_num sets. That would be this:

c->sets = malloc(c->set_num*sizeof(set));

(casting the result is unnecessary in C) or this:

c->sets = malloc(c->set_num*sizeof(*c->sets));

Because you are not allocating enough space, you later try to access space beyond what you allocated. The resulting behavior is undefined, but it is not at all surprising if that memory is unexpectedly modified, as it may easily be assigned to some other dynamically allocated block.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.