简体   繁体   中英

Difference in behavior between clang and gcc?

I'm writing a C function to simulate a cache given an address trace. The function works as expected when compiled on my mac using gcc (really clang). gcc --version on my mac returns this:

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)

When I compile the same program on linux using gcc, the returns are way off, and eC & hC in my program (cache eviction counter and hit counter) are in the hundreds of thousands, when they should be below 10. When typing gcc --version on the linux machine, it returns this:

gcc (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3

Here is the program:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <limits.h>
    #include <getopt.h>
    #include "cachelab.h"

    typedef struct{
        int v;
        int t;
        int LRU;
    } block;

    typedef struct{
        block *blocks;
    } set;

    typedef struct{
        set *sets;
    } cache;

    void simulate(int s, int E, int b, char* file, int* hC, int* mC, int* eC)
    {
        int numSets = (1 << s);
        char operation;
        int address;
        int size;
        int curTag;
        int curSet;
        int maxLRU = 0;
        int curLRU = 0;
        int check = 0;

    cache c;
    set *sets = malloc(sizeof(set) * numSets);
    c.sets = sets;

    int i = 0;
    while(i < numSets)
    {
        c.sets[i].blocks = malloc(sizeof(block) * E);
        for (int j = 0; j < E; j++)
        {
            c.sets[i].blocks[j].v = 0;
            c.sets[i].blocks[j].t = INT_MIN;
            c.sets[i].blocks[j].LRU = 0;
        }

        i++;
    }

    FILE *f = fopen(file, "r");
    while(fscanf(f," %c %x,%d", &operation, &address, &size) != EOF)
    {
        check = 0;
        curTag = ((unsigned int) address) >> (s+b);
        curSet = (address >> b) & ((1 << s) - 1);
        for (int i = 0; i < E; i++)
        {
            c.sets[curSet].blocks[i].LRU++;
            if(c.sets[curSet].blocks[i].LRU >= maxLRU)
            {
                maxLRU = c.sets[curSet].blocks[i].LRU;
                curLRU = i;
            }
            if(curTag == c.sets[curSet].blocks[i].t)
            {
                *hC = *hC + 1;
                if (operation == 'M')
                {
                    *hC = *hC + 1;
                }
                c.sets[curSet].blocks[i].LRU = 0;
                check = 1;
            }
        }
        if(check == 0)
        {
            for(int i = 0; i < E; i++)
            {
                if(c.sets[curSet].blocks[i].v == 0)
                {
                    *mC = *mC + 1;
                    if (operation == 'M')
                    {
                        *hC = *hC + 1;
                    }
                    c.sets[curSet].blocks[i].v = 1;
                    c.sets[curSet].blocks[i].LRU = 0;
                    c.sets[curSet].blocks[i].t = curTag;
                    check = 1;
                    break;
                }
            }
        }
        if(check == 0)
        {
            *eC = *eC + 1;
            *mC = *mC + 1;
            if (operation == 'M')
            {
                *hC = *hC + 1;
            }
            c.sets[curSet].blocks[curLRU].t = curTag;
            c.sets[curSet].blocks[curLRU].v = 1;
            c.sets[curSet].blocks[curLRU].LRU = 0;
        }
    }
    }

    int main(int argc, char** argv)
    {
    int hitCount, missCount, evictionCount;

    int s, E, b;
    char *file;
    char opt;
    while((opt = getopt(argc,argv,"v:h:s:E:b:t:")) != -1)
    {
        switch(opt){
            case 'v':
                break;
            case 'h':
                break;
            case 's':
                s = atoi(optarg);
                break;
            case 'E':
                E = atoi(optarg);
                break;
            case 'b':
                b = atoi(optarg);
                break;
            case 't':
                file = optarg;
                break;
            default:
                exit(1);
        }
    }
    simulate(s, E, b, file, &hitCount, &missCount, &evictionCount);

    printSummary(hitCount, missCount, evictionCount);
    return 0;
}

EDIT:

I understand that this is due to a difference between clang and gcc. Does anyone have any information about how I can go about fixing this discrepancy?

Here is cachelab.c:

/*
 * cachelab.c - Cache Lab helper functions
 */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "cachelab.h"
#include <time.h>

trans_func_t func_list[MAX_TRANS_FUNCS];
int func_counter = 0;

/*
 * printSummary - Summarize the cache simulation statistics. Student cache simulators
 *                must call this function in order to be properly autograded.
 */
void printSummary(int hits, int misses, int evictions)
{
    printf("hits:%d misses:%d evictions:%d\n", hits, misses, evictions);
    FILE* output_fp = fopen(".csim_results", "w");
    assert(output_fp);
    fprintf(output_fp, "%d %d %d\n", hits, misses, evictions);
    fclose(output_fp);
}

/*
 * initMatrix - Initialize the given matrix
 */
void initMatrix(int M, int N, int A[N][M], int B[M][N])
{
    int i, j;
    srand(time(NULL));
    for (i = 0; i < N; i++){
        for (j = 0; j < M; j++){
            // A[i][j] = i+j;  /* The matrix created this way is symmetric */
            A[i][j]=rand();
            B[j][i]=rand();
        }
    }
}

void randMatrix(int M, int N, int A[N][M]) {
    int i, j;
    srand(time(NULL));
    for (i = 0; i < N; i++){
        for (j = 0; j < M; j++){
            // A[i][j] = i+j;  /* The matrix created this way is symmetric */
            A[i][j]=rand();
        }
    }
}

/*
 * correctTrans - baseline transpose function used to evaluate correctness
 */
void correctTrans(int M, int N, int A[N][M], int B[M][N])
{
    int i, j, tmp;
    for (i = 0; i < N; i++){
        for (j = 0; j < M; j++){
            tmp = A[i][j];
            B[j][i] = tmp;
        }
    }
}



/*
 * registerTransFunction - Add the given trans function into your list
 *     of functions to be tested
 */
void registerTransFunction(void (*trans)(int M, int N, int[N][M], int[M][N]),
                           char* desc)
{
    func_list[func_counter].func_ptr = trans;
    func_list[func_counter].description = desc;
    func_list[func_counter].correct = 0;
    func_list[func_counter].num_hits = 0;
    func_list[func_counter].num_misses = 0;
    func_list[func_counter].num_evictions =0;
    func_counter++;
}

You forgot to initialize the counters and flags so they start at undefined values. The following lines:

int hitCount, missCount, evictionCount;
int s, E, b;

should be:

int hitCount = 0, missCount = 0, evictionCount = 0;
int s = 0, E = 0, b = 0;

It just happens that the initial values happen to be lower on the mac so you're not getting correct results on the mac either (at least not guaranteed since the initial value is undefined).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM