It’s been a while since I’ve written C so this bug makes me feel like I’m losing my mind. I’m writing a program to model a simple cache. Don’t worry about the details.
The problem is when I initialize the cache. In the line in SA_cacheInit:
cur_lru = cache->sets + i;//[i];
Using brackets fails and upon inspection in GDB it ends up giving a null pointer even for i = 0. However it works if I just use normal pointer arithmetic. What am I doing wrong?
typedef struct s_LRUnode {
int tag;
bool valid;
bool dirty;
struct s_LRUnode *next;
struct s_LRUnode *prev;
} LRUnode;
typedef struct s_LRU {
size_t size;
LRUnode *head;
LRUnode *tail;
} LRU;
typedef struct s_SA_cache {
size_t blocksize;
size_t num_blocks;
size_t set_size;
LRU **sets;
} SA_cache;
void cachesim_init(int blocksize, int cachesize, int ways) {
cache = malloc(sizeof(SA_cache));
if ( cache != NULL ) {
assert( powerOfTwo(cachesize) && powerOfTwo(blocksize) );
cache->num_blocks = cachesize / blocksize;
cache->blocksize = blocksize;
cache->set_size = ways;
cache->sets = malloc(sizeof(LRU)*cache->num_blocks); //cache->num_blocks*ways);
if (cache->sets == NULL) {
printf(stderr, "Malloc failed in %s\n", func);
}
SA_cacheInit(cache, cache->num_blocks, ways);
} else {
fprintf(stderr, "Could not allocate memory for cache\n");
exit(-1);
}
}
void SA_cacheInit(SA_cache *cache, size_t num_blocks, size_t size) {
int i;
LRU *cur_lru;
for (i = 0; i < num_blocks; i++) {
cur_lru = cache->sets + i;//[i];
cur_lru->size = size;
cur_lru->head = NULL;
cur_lru->tail = NULL;
}
}
It seems to me that
SA_cache::setsshould have typeLRU*rather thanLRU**. As Jamey pointed out, what you have posted here won’t compile cleanly otherwise. The rest of this answer assumes that type isLRU*.When you write:
cur_lrugets the value at theith element ofcache->sets, which in your case was zero (likely since your process has only just seen this memory for the first time).If you want to use array subscripting, you need to use the address-of operator (
&):cur_lruthen gets the address of theith element of cache->sets. This is functionally identical to the pointer arithmetic you posted.