動的に割り当てられた構造体の 2D 配列を含むプロジェクトに取り組んでいます。これらの各構造体の内部には、動的に割り当てられた int の配列があります。プログラムは完全に実行されていますが、配列の 2 番目の次元のメンバーが複数ある場合にクリーンアップするときに、次のエラーが発生します。
*** glibc detected *** cache: double free or corruption (out): 0x0000000009f172f0 ***
それに続く長いバックトレースとメモリ マップがあり、それが役立つ場合は、喜んで提供します。割り当てと解放のコードは次のようになります。ブロック構造体の内容は次のとおりです。
typedef struct blockStruct {
int valid;
int tag;
int dirty;
int mru;
int* data;
} block;
割り当て: blocksPerSet が 1 より大きい場合、割り当て解除は失敗します。
/* Make cache */
block** cache;
cache = malloc(numberOfSets * sizeof(block*));
for (i = 0; i < numberOfSets; i++) {
cache[i] = malloc(blocksPerSet * sizeof(block));
}
int j = 0;
for (i = 0; i < numberOfSets; i++) {
for (j = 0; j < blocksPerSet; j++) {
cache[i][j].valid = 0;
cache[i][j].data = malloc(blockSizeInWords*sizeof(int));
cache[i][j].mru = 0;
}
}
割り当て解除:
for (i = 0; i < numberOfSets; i++) {
for (j = 0; j < blocksPerSet; j++) {
free(cache[i][j].data);
}
free(cache[i]);
}
free(cache);
前もって感謝します。
編集:問題を2つの機能の1つに絞り込みました。それらは saveToCache と loadToCache であり、機能的に非常に似ています。メイン関数は常に最初に loadToCache を呼び出し、次に saveToCache を呼び出したり、loadToCache を呼び出したりするループです。これら 2 つの呼び出しのいずれかをコメントアウトすると、どちらに関係なく、エラーは発生しません。
EDIT2: loadToCache を使用する前に saveToCache を使用した場合にのみエラーが発生することにも気付きました。
int saveToCache(block** cache, int blockSizeInWords, int numberOfSets,
int blocksPerSet, stateType* statePtr, int address,
int saveData)
int setNumber = (address / blockSizeInWords) % numberOfSets;
int targetTag = address / blockSizeInWords / numberOfSets;
int offset = address % blockSizeInWords;
int blockStart = address / blockSizeInWords * blockSizeInWords;
int i = 0;
/* If a hit is found, set MRU and return */
for (i; i < blocksPerSet; i++) {
if (cache[setNumber][i].valid == 1) {
if (cache[setNumber][i].tag == targetTag) {
cache[setNumber][i].mru = 1;
cache[setNumber][i].data[offset] = saveData;
cache[setNumber][i].dirty = 1;
printAction(address, 1, processorToCache);
return cache[setNumber][i].data[offset];
}
}
}
int j;
/* Find out if there is an empty space. If so, allocate and return */
for (i = 0; i < blocksPerSet; i++) {
if (cache[setNumber][i].valid == 0) {
cache[setNumber][i].valid = 1;
cache[setNumber][i].tag = targetTag;
cache[setNumber][i].dirty = 1;
cache[setNumber][i].mru = 1;
for (j = 0; j < blockSizeInWords; j++) {
cache[setNumber][i].data[j] = (*statePtr).mem[blockStart + j];
}
printAction(blockStart, blockSizeInWords, memoryToCache);
cache[setNumber][i].data[offset] = saveData;
printAction(address, 1, processorToCache);
return cache[setNumber][i].data[offset];
}
}
int allMRUSet = 1;
/* Find LRU and replace */
int evictedAddress;
for (i = 0; i < blocksPerSet; i++) {
/* Save back to memory if block is dirty */
if (cache[setNumber][i].mru == 0) {
evictedAddress = blockSizeInWords * (setNumber + cache[setNumber][i].tag
* numberOfSets);
if (cache[setNumber][i].dirty == 1) {
for (j = 0; j < blockSizeInWords; j++)
(*statePtr).mem[blockStart + j] = cache[setNumber][i].data[j];
printAction(evictedAddress, 1, cacheToMemory);
}
else
printAction(evictedAddress, 1, cacheToNowhere);
cache[setNumber][i].valid = 1;
cache[setNumber][i].tag = targetTag;
cache[setNumber][i].dirty = 1;
cache[setNumber][i].mru = 1;
for (j = 0; j < blockSizeInWords; j++) {
cache[setNumber][i].data[j] = (*statePtr).mem[blockStart + j];
}
printAction(blockStart, blockSizeInWords, memoryToCache);
cache[setNumber][i].data[offset] = saveData;
/* Check if all MRU blocks are set. If yes, unset all. */
for (j = 0; j < blocksPerSet; j++) {
if (cache[setNumber][j].mru == 0)
allMRUSet = 0;
}
if (allMRUSet == 1) {
for (j = 0; j < blocksPerSet; j++) {
cache[setNumber][j].mru = 0;
}
/* Re-set most recently used block */
cache[setNumber][i].mru = 1;
}
printAction(address, 1, processorToCache);
return cache[setNumber][i].data[offset];
}
}
/* If we get this far, all MRU bits are set. Un-set all of them. */
for (i = 0; i < blocksPerSet; i++) {
cache[setNumber][i].mru = 0;
}
/* Place data in item 0 of set and set MRU */
/* Save back to memory if block is dirty */
evictedAddress = blockSizeInWords * (setNumber + cache[setNumber][0].tag
* numberOfSets);
if (cache[setNumber][0].dirty == 1) {
for (j = 0; j < blockSizeInWords; j++)
(*statePtr).mem[blockStart + j] = cache[setNumber][0].data[j];
printAction(evictedAddress, 1, cacheToMemory);
}
else
printAction(evictedAddress, 1, cacheToNowhere);
cache[setNumber][0].valid = 1;
cache[setNumber][0].tag = targetTag;
cache[setNumber][0].dirty = 1;
cache[setNumber][0].mru = 1;
for (i = 0; i < blockSizeInWords; i++) {
cache[setNumber][0].data[i] = (*statePtr).mem[blockStart + j];
}
printAction(blockStart, blockSizeInWords, memoryToCache);
cache[setNumber][0].data[offset] = saveData;
printAction(address, 1, processorToCache);
return cache[setNumber][0].data[offset];
}