我正在研究一个涉及动态分配的二维结构数组的项目。在这些结构中的每一个内部都是一个动态分配的整数数组。该程序执行得很好,但是当我的数组的第二维有多个成员时需要清理时,我收到此错误:
*** 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);
提前致谢。
编辑:我将问题缩小到两个功能之一。它们是 saveToCache 和 loadToCache,在功能上非常相似。主函数是一个循环,它总是先调用 loadToCache,然后可能调用 saveToCache 或调用 loadToCache。如果我注释掉这两个调用之一,无论是哪一个,我都不会收到任何错误。
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];
}