2

C を書いてからしばらく経っているので、このバグのせいで正気を失っているように感じます。単純なキャッシュをモデル化するプログラムを書いています。詳細は気にしないでください。

問題は、キャッシュを初期化するときです。SA_cacheInit の行:

cur_lru = cache->sets + i;//[i];

括弧の使用は失敗し、GDB で検査すると、i = 0 の場合でも null ポインターが返されます。ただし、通常のポインター演算を使用するだけで機能します。私は何を間違っていますか?


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; } }

4

2 に答える 2

2

ではなくSA_cache::setstype を持つべきだと私には思えます。Jamey が指摘したように、ここに投稿したものは、そうでなければきれいにコンパイルされません。この回答の残りの部分では、タイプが.LRU*LRU**LRU*

あなたが書くとき:

cur_lru = cache->sets[i];

cur_lruのth 要素のを取得します。これは、あなたの場合はゼロでした (おそらく、プロセスがこのメモリを初めて見ただけなので)。icache->sets

&配列の添え字を使用する場合は、アドレス演算子 ( )を使用する必要があります。

cur_lru = &cache->sets[i];

cur_lru次に、cache->setsの番目の要素のアドレスを取得します。iこれは、投稿したポインター演算と機能的に同じです。

于 2012-11-11T06:50:48.447 に答える
1

の型はcache->setsですので、LRU **の型cache->sets + iLRU **です。結果を に割り当てるとLRU *cur_lru、コンパイラの警告が表示されることを期待していました。(警告を有効にせずにビルドしていますか?)

互換性のないポインター型からのこの割り当ては、sets配列内のポインターをLRU構造体のフィールドであるかのように書き込んでいることを意味します。


編集: よく読んでみると、添え字が正しいことを理解していることがわかります。また、このタイプのエラーを導入した場合にのみコードが機能することを報告しています。私は上記のことを支持しており、実際、GCC は「警告: 互換性のないポインター型からの割り当て」を報告しています-Wall

このコードで私が見つけることができる他の唯一の問題はmallocsets配列の場合、各要素のサイズをsizeof(LRU)ではなく にすることsizeof(LRU *)です。ただし、使用しているプラ​​ットフォームが何であれ、ほぼ確実にLRU構造体が へのポインターよりも大きくなるLRUため、表示されている症状を説明することはできません。

最適化 (gcc -O2または同様のもの)を使用してコンパイルすると、gdb報告される情報が誤解を招く可能性があることに注意してください。型エラーを導入すると、初期化の最適化を妨げているgcc可能性があり、それが唯一の理由で、gdb期待どおりに報告される可能性があります。

gcc -Wallすべての警告をコンパイルして修正することを強くお勧めします。それでも問題が解決しない場合は、 Valgrindでプログラムを実行して、さまざまなメモリ エラーをキャッチします。

于 2012-11-10T01:15:16.833 に答える