已经有一段时间了,所以这个错误使我觉得自己失去了理智。我正在编写一个程序来建模简单的缓存。不必担心细节。
问题是当我初始化缓存时。在sa_cacheinit的行中:
cur_lru = cache->sets + i;//[i];
使用括号失败,在GDB中检查时,即使在i = 0中,它最终都会给出一个无效指针。但是,如果我只使用普通指针算术,则可以使用。我在做什么错?
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 %sn", func);
}
SA_cacheInit(cache, cache->num_blocks, ways);
} else {
fprintf(stderr, "Could not allocate memory for cachen");
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::sets
should have type LRU*
rather than LRU**
. As Jamey pointed out, what you have posted here won't compile cleanly otherwise. The rest of this answer assumes that type is LRU*
.
When you write:
cur_lru = cache->sets[i];
cur_lru
在 cache->sets
的i
元素上获取 value ,在您的情况下为零(可能是因为您的过程首次只看到了此内存)。
如果要使用数组订阅,则需要使用操作地址(&
):
cur_lru = &cache->sets[i];
cur_lru
然后获取cache-> sets的i
元素的地址。这在功能上与您发布的指针算术相同。
由于cache->sets
的类型为LRU **
,因此cache->sets + i
的类型也为LRU **
。当您将结果分配给LRU *cur_lru
时,我希望您会收到编译器警告。(您是否在没有警告的情况下建造?)
来自不兼容的指针类型的此作业意味着您正在写入sets
数组中的指针,就好像它们是LRU
结构的字段一样。
编辑:在更仔细的阅读中,我看到您知道订阅应该是正确的,并且您报告该代码仅在引入此类型错误时才有效。我支持上述内容,实际上GCC报告"警告:来自不兼容的指针类型的分配",即使没有-Wall
。
我在此代码中可以找到的唯一其他问题是,当您malloc
sets
数组时,您将每个元素大小为sizeof(LRU)
,而不是sizeof(LRU *)
。但是,几乎可以肯定的是,无论您使用哪种平台,LRU
结构都比LRU
的指针更大,因此不应该解释您看到的症状。
请注意,如果您对优化进行编译(gcc -O2
或类似),则gdb
报告的信息可能会误导。当您引入类型错误时,您可能会阻止gcc
优化初始化,并且可能是gdb
报告您期望的唯一原因。
我强烈建议您使用gcc -Wall
编译并修复所有警告。然后,如果尚未解决问题,请在Valgrind下运行您的程序以捕获各种内存错误。