#c #caching #segmentation-fault #coredump
Вопрос:
Я заполняю код для симулятора кэша в C. Как это работает, вам предоставляется входной файл с командами, вы должны отслеживать результаты этого ввода, имитируя функции кэша, чтобы мы могли отслеживать попадания и пропуски в кэш. Я написал следующий код, но, похоже, у меня возникли проблемы с методом ReplayTrace. Строка «AccessData(addr)» выдает «ошибку сегментации (дамп ядра)». Я осознаю, что это означает, что я пытаюсь получить доступ к чему-то, на доступ к чему у меня нет разрешения, или что оно больше не существует, или находится вне зоны действия. Я понятия не имею, как еще вызвать эту функцию. Я публикую весь свой код, потому что не хочу делать предположений о том, в чем может заключаться проблема. Кто-нибудь может сказать, где я совершаю ошибку?
/* TODO - COMPLETE THIS FUNCTION
* accessData - Access data at memory address addr.
* If it is already in cache, increase hit_count
* If it is not in cache, bring it in cache, increase miss count.
* Also increase eviction_count if a line is evicted.
*
* You will manipulate data structures allocated in initCache() here
* Implement Least-Recently-Used (LRU) cache replacement policy
*/
void accessData(mem_addr_t addr)
{
int i;
//pulling out the set and tag bits of address
mem_addr_t set = (addr >> b) amp; set_bits;
mem_addr_t tag = addr >> (s b);
cache_set_t cache_set = cache[set];
/* judge if hit */
for (i = 0; i < E; i)
{
/* hit */
if (cache_set[i].valid amp;amp; cache_set[i].tag == tag)
{
if (verbosity)
printf("hit ");
hit_count;
/* update entry whose lru is less than the current lru (newer) */
for (int j = 0; j < E; j)
if (cache_set[j].valid amp;amp; cache_set[j].lru < cache_set[i].lru)
cache_set[j].lru;
cache_set[i].lru = 0;
return;
}
}
/* missed */
if (verbosity)
printf("miss ");
miss_count;
/* find the biggest lru or the first invlaid line */
int j, maxIndex = 0;
unsigned long long maxLru = 0;
for (j = 0; j < E amp;amp; cache_set[j].valid; j)
{
if (cache_set[j].lru >= maxLru)
{
maxLru = cache_set[j].lru;
maxIndex = j;
}
}
if (j != E)
{
/* found an invalid entry */
/* update other entries */
for (int k = 0; k < E; k)
if (cache_set[k].valid)
cache_set[k].lru;
/* insert line */
cache_set[j].lru = 0;
cache_set[j].valid = 1;
cache_set[j].tag = tag;
}
else
{
/* all entry is valid, replace the oldest one*/
if (verbosity)
printf("eviction ");
eviction_count;
for (int k = 0; k < E; k)
cache_set[k].lru;
cache_set[maxIndex].lru = 0;
cache_set[maxIndex].tag = tag;
}
}
/* TODO - FILL IN THE MISSING CODE
* replayTrace - replays the given trace file against the cache
* reads the input trace file line by line
* extracts the type of each memory access : L/S/M
* YOU MUST TRANSLATE one "L" as a load i.e. 1 memory access
* YOU MUST TRANSLATE one "S" as a store i.e. 1 memory access
* YOU MUST TRANSLATE one "M" as a load followed by a store i.e. 2 memory accesses
* Ignore instruction fetch "I"
*/
void replayTrace(char* trace_fn)
{
char buf[1000];
mem_addr_t addr=0;
unsigned int len=0;
FILE* trace_fp = fopen(trace_fn, "r");
int count = 0;
if(!trace_fp){
fprintf(stderr, "%s: %sn", trace_fn, strerror(errno));
exit(1);
}
while( fgets(buf, 1000, trace_fp) != NULL) {
if(buf[1]=='S' || buf[1]=='L' || buf[1]=='M') {
sscanf(buf 3, "%llx,%u", amp;addr, amp;len);
if(verbosity)
printf("%c %llx,%u ", buf[1], addr, len);
// TODO - MISSING CODE
// now you have:
// 1. address accessed in variable - addr
// 2. type of acccess(S/L/M) in variable - buf[1]
// call accessData function here depending on type of access
switch (buf[1])
{
case 'L':
case 'S':
accessData(addr);
count;
break;
case 'M':
accessData(addr);
accessData(addr);
count;
break;
default:
break;
}
if (verbosity)
printf("n");
}
}
fclose(trace_fp);
}
—редактировать—
Выход Valgrind:
Command: ./csim -t traces/dave.trace -s 8 -E 4 -b 12
==4155737==
==4155737== Invalid read of size 8
==4155737== at 0x1095B2: accessData (csim.c:144)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== Address 0x4b9c040 is 0 bytes after a block of size 0 alloc'd
==4155737== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4155737== by 0x10938A: initCache (csim.c:99)
==4155737== by 0x109DB7: main (csim.c:336)
==4155737==
==4155737== Invalid read of size 1
==4155737== at 0x1095E2: accessData (csim.c:150)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==4155737==
==4155737==
==4155737== Process terminating with default action of signal 11 (SIGSEGV)
==4155737== Access not within mapped region at address 0x0
==4155737== at 0x1095E2: accessData (csim.c:150)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== If you believe this happened as a result of a stack
==4155737== overflow in your program's main thread (unlikely but
==4155737== possible), you can try to increase the size of the
==4155737== main thread stack using the --main-stacksize= flag.
==4155737== The main thread stack size used in this run was 8388608.
==4155737==
==4155737== HEAP SUMMARY:
==4155737== in use at exit: 472 bytes in 2 blocks
==4155737== total heap usage: 3 allocs, 1 frees, 4,568 bytes allocated
==4155737==
==4155737== LEAK SUMMARY:
==4155737== definitely lost: 0 bytes in 0 blocks
==4155737== indirectly lost: 0 bytes in 0 blocks
==4155737== possibly lost: 0 bytes in 0 blocks
==4155737== still reachable: 472 bytes in 2 blocks
==4155737== suppressed: 0 bytes in 0 blocks
==4155737== Rerun with --leak-check=full to see details of leaked memory
==4155737==
==4155737== For lists of detected and suppressed errors, rerun with: -s
==4155737== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)```
Комментарии:
1. Ни один из этих кодов не выглядит так, как будто он может вызвать ошибку seg. Вероятно, вы сделали что-то ранее, что вызвало неопределенное поведение и повреждение памяти.
2. Не видя ввода, для которого вы sscanf, кажется, что addr равен НУЛЮ, поэтому убедитесь, что это не так, прежде чем вызывать функцию? Если у вас есть доступ к valgrind, запустите программу и в этом разделе, чтобы получить помощь. Но я предполагаю, что addr неправильно анализируется из входного файла, и это вызывает его.
3. Когда я комментирую строку «AccessData(addr)», все работает нормально.
4. @firmament Я никогда раньше не использовал Valgrind, поэтому я работаю над тем, чтобы понять этот вывод прямо сейчас. Но на случай, если вы сможете быстро это понять, я добавил вывод в сообщение
5. @небосвод не уверен, правильно ли я тебя пометил ^