имитатор кэша ошибок дампа ядра ошибки сегментации

#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. @небосвод не уверен, правильно ли я тебя пометил ^