1

I am new to C.

I declared three structs

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;


cache* init(int s, int b, int E){
    cache* c =malloc(sizeof(cache)) ;
    assert(c!= NULL);

   c->set_num = (1<<s);
   c->line_num = E;
   c->sets = malloc(c->set_num*sizeof(set));
   for (int i=0;i<s;i++){
       c->sets[i].empty=i;
       c->sets[i].line=malloc(E*sizeof(line));
       c->sets[i].insert=0;
   }
return c;
}

The function is really simple. c.sets is an array and c->sets[i].line is also an array.

However, it seems that it does not create an array.Where did I wrong? I use xcode to debug this method, and c.sets is not an array, it only has on element, and c->sets[i].empty is always 0. If I use gcc -W -Wall -pedantic -std=c99 -g to compile, c->sets[i].empty updates. On Xcode, it does not. Thanks,

Sean

6
  • I declared typedef struct{ int access_time; int tag; int valid; }line; Commented Apr 30, 2015 at 22:52
  • Yeah, I missed that. What are values are you calling init() with? If s is 0 then the results you get are expected. Commented Apr 30, 2015 at 22:54
  • s =4, E =1,b =4. So I expect the cache has 4 sets, each set has one line. I put a break point after c->sets[i].empty=i; it supposes to be 0,1,2 ,3, but always 0. Commented Apr 30, 2015 at 22:58
  • Why do you expect the cache to have 4 sets? You are setting c->set_num to 1 << s, which is 2 raised to the sth power, and then allocating that many sets. Commented Apr 30, 2015 at 23:21
  • my bad, it should be 16 sets. S =16, s =4. Commented Apr 30, 2015 at 23:28

1 Answer 1

2

Your loop

for (int i = 0; i < s; i++) {
  c->sets[i].empty = i;
  c->sets[i].line = malloc(E * sizeof(line));
  c->sets[i].insert = 0;
}

only iterates over s values, but there are 1 << s values allocated. This leaves some uninitialised values in the set array, and accessing them without initialising them is undefined behaviour. They may be set to arbitrary values, or they may also be zeroed by your debugger or compiler, etc.

Try this instead, if you intended to have 1 << s sets:

for (int i = 0; i < c->set_num; i++) {
    c->sets[i].empty = i;
    c->sets[i].line = malloc(E * sizeof *c->sets[i].line);
    assert(NULL != c->sets[i].line);
    c->sets[i].insert = 0;
}

If instead you intended to only have s many sets, then you need this:

c->set_num = s; // you must know how many there are to be able to free them
c->line_num = E;
c->sets = malloc(s * sizeof *c->sets); // could use c->set_num instead of s here
assert(NULL != c->sets);
for (int i = 0; i < s; i++) { // ditto here
  ...
}

(I prefer using *c->sets[i].line in the malloc() call because it means if I change the type of the variable it is still correct.)

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

5 Comments

@SeawindShi Fix your loop first. The compiler is allowed to do literally anything if you have undefined behaviour. And that assert is to check the result of your malloc() for the line. It has nothing to do with the uninitialised values.
Thanks for your help. yes, it should be 2^s instead of s. I changed that, I also added assert(NULL != c->sets[i].line); and assert(NULL != c->sets); They are not null. But even i =1, c->sets[i].empty still equals 0, it should equal to 1 as long as i >=1.
@SeawindShi Here's a paste that runs, on my machine, compiled with gcc or clang, that runs without errors and sets empty, and prints the result. It works for me (compile flags -W -Wall -pedantic -std=c99 -g). Perhaps there is something you have not mentioned, or maybe your debugger is doing something odd.
One thing I wonder is that when I declared my cache typedef struct{ int set_num; int line_num; set *sets; }cache; sets is an array of struct set. I thought I should use c->sets[i]->empty instead of c->sets[i].empty. But xcode shows error if I use c->sets[i]->empty
x->y is equivalent to (*x).y, you use to when x is a pointer to a struct. In this case, c->sets[i] is a struct, not a pointer to a struct, so . is correct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.