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).
Related
I'm trying to learn how to multithread with c, and thought that the longest palindromic subsequence problem would be a good place to start.
The idea is that we run two threads and compare their results to find the answer. One thread deals with "odd" subsequences, the other with "even" ones.
Although the code below seems to work, my question is: where in the program should I check for multi-threading errors? It is very new to me so I just need to know what parts may be prone to the issues that multi-threading brings.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct str{
char* seq;
int len;
};
void *odd(void* arg){
struct str index = *(struct str*)arg;
int maxAns = 1;
for(int i = 1; i < index.len; i++){
int low = i - 1;
int high = i + 1;
int currMax = 1;
while(low >= 0 && high < index.len && index.seq[low] == index.seq[high]){
low--;
high++;
currMax=currMax+2;
}
if(currMax > maxAns){
maxAns = currMax;
}
}
int* res = malloc(sizeof(int));
*res = maxAns;
free(arg);
return (void*)res;
}
void *even(void* arg){
struct str index = *(struct str*)arg;
int maxAns = 0;
for(int i = 0; i < index.len; i++){
int low = i;
int high = i + 1;
int currMax = 0;
while(low >= 0 && high < index.len && index.seq[low] == index.seq[high]){
low--;
high++;
currMax=currMax+2;
}
if(currMax > maxAns){
maxAns = currMax;
}
}
int* res = malloc(sizeof(int));
*res = maxAns;
free(arg);
return (void*)res;
}
int main(void){
char seq0[] = "aaasaaasadaadsdafa";
int len = sizeof(seq0)/sizeof(seq0[0])-1;
struct str* s0 = malloc(sizeof(struct str));
struct str* s1 = malloc(sizeof(struct str));
s0->seq = (char*)seq0;
s1->seq = (char*)seq0;
s0->len = len;
s1->len = len;
pthread_t t0;
pthread_t t1;
int* res0;
int* res1;
if (pthread_create(&t0, NULL, &odd, s0)!=0){
return 0;
}
if (pthread_create(&t1, NULL, &even, s1)!=0){
return 00;
}
if(pthread_join(t0, (void**)&res0)!=0){
return 1;
}
if(pthread_join(t1, (void**)&res1)!=0){
return 11;
}
if(*res0 > *res1){
printf("%d\n", *res0);
}else{
printf("%d\n", *res1);
}
free(s0);
free(s1);
return 0;
}
I am getting the error variable sized object may not be initialized and I don't understand why.
Could someone show me how to fix this line?
int arr[size] = (int *)(augs->one);
Here is my code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
int count = 0;
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct structure {
int two;
int *one;
};
void *sort(void *augments) {
struct structure *augs = (struct structure*)augments;
int i = 0;
int size = 1;
size = augs->two;
int arr[size] = (int *)(augs->one);
//int *arr = (int *)data;
//printf("sizeof:%d\n", sizeof(arr));
qsort(arr, size, sizeof(int), cmpfunc);
printf("finaloutput:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return NULL;
}
int main(int argc, char *argv[]) {
FILE *myFile;
myFile = fopen("data.txt", "r");
// number of lines in file
char charicter;
for (charicter = getc(myFile); charicter != EOF; charicter = getc(myFile)) {
if (charicter == '\n') {
count++;
}
}
printf("count is %d\n", count);
int numberArray[count];
int i = 0;
if ((myFile = fopen("data.txt", "r"))) {
while ((fscanf(myFile, "%d", &numberArray[i]) != EOF)) {
++i;
}
fclose(myFile);
}
assert(argv[1] != NULL);
int num = atoi(argv[1]); //num equals number input
int arrayarray[num - 1][(count / num)];
int idx;
for (i = 0; i < (count); i++) {
printf("numberarray[%d]= %d\n", i, numberArray[i] /*[0],numberArray[i][1]*/);
}
for (i = 1; i < num + 1; i++) {
for (idx = 0; idx < (count / num); idx++) {
arrayarray[i - 1][idx] = numberArray[i * idx];
}
}
///*
for (i = 0; i < ((count / num)); i++) {
printf("arrayarray[0]=%d\n", arrayarray[0][i]);
}
//*/
int lastarray[((count / num) + (count % num))];
for (idx = 0; idx < ((count / num) + (count % num)); idx++) {
lastarray[idx] = numberArray[idx + ((count / num) * (num - 1))];
}
for (i = 0; i < ((((count / num) + (count % num)))); i++) {
printf("lastaray[%d]=%d\n", i, lastarray[i]);
}
//*******************
pthread_t thread_id_arr[num];
for (i = 0; i < num; i++) {
pthread_t tid;
struct structure *augs;
if (i != (num - 1)) {
augs = malloc(sizeof(struct structure) + sizeof(int) + sizeof(int) * num);
(*augs).one = arrayarray[i];
(*augs).two = (count / num);
pthread_create(&tid, NULL, sort, augs);
} else {
(*augs).one = lastarray;
(*augs).two = (count / num) + (count % num);
pthread_create(&tid, NULL, sort, augs);
//pthread_create(&tid, NULL, sort, (void*)lastarray);
}
thread_id_arr[i] = tid;
}
for (i = 0; i < num; i++) {
pthread_join(thread_id_arr[i], NULL);
}
return 0;
}
As others pointed out, you can't initialize a Variable Length Array with a pointer, like you are doing. However, you don't actually need a VLA at all. Use this instead :
int *arr = augs -> one;
You want to act directly on the array that is passed into the thread, not make a copy of it.
That being said, I see another problem. In the loop that spawns the sorting threads, you are not allocating a new args on the last loop iteration, it reuses the allocated args from the previous iteration, which can cause disaster for the 2nd-to-last thread. You need to move the malloc() call above the if.
Also, the malloc() is allocating more memory than your threads actually use. You only need to allocate enough memory for just the struct by itself, not for any integers following the struct.
Also, when each thread is done using the allocated args that it is given, it needs to free() the args to avoid leaking memory.
I'm having problems understanding how to write code that solves the following problem: I have a structure containing a 2D-array. Then I have a recursive function that take a pointer to the structure as an argument and I want the recursive function to be able to manipulate the structure sent, not a local copy.
The struct is initialized in the function initStruct, where memory for the 2D-array is allocated. The recursive function builds up an array and at a specific point calls a function to insert it into the structure's array.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** spBasis(int);
void mpBasis(int**, int, int, int, int, int, int, int*, struct mpBasis *, int, int);
void initMpBasis(struct mpBasis *, int, int);
void insertMpState(struct mpBasis *, int *);
struct mpBasis {
int** basis;
int size;
int capacity;
};
int main() {
int a, b, c, d;
char maxE[256];
char noParticles[256];
char P[256];
char M[256];
FILE *fp;
int **spStates;
struct mpBasis *mp;
int mpState[6] = {0, 0, 0, 0, 0, 0};
printf("Input max e for sp states, no of particles, parity (1 for odd and 0 for even) and magnetic projection: ");
gets(maxE);
gets(noParticles);
gets(P);
gets(M);
spStates = spBasis(atoi(maxE));
fp = fopen("spStates.txt", "a+");
fprintf(fp, "E\tj\tl\tm\n");
for (a = 0; a < 330; a++) {
fprintf(fp, "State %d: ", a+1);
for (b = 0; b < 4; b++) {
fprintf(fp, "%d\t", spStates[a][b]);
}
fprintf(fp, "\n");
}
mp = malloc(sizeof(struct mpBasis));
initMpBasis(mp, 5449, 6);
for (c = 0; c < 5449; c++) {
for (d = 0; d < 6; d++) {
fprintf(fp, "%d: %d\t", c, mp->basis[c][d]);
}
fprintf(fp, "\n");
}
printf("%p\n", (void*) mp);
printf("hello 3");
mpBasis(spStates, 0, atoi(maxE), 0, atoi(M), 0, atoi(P), mpState, mp, 0, 0);
fclose(fp);
return 0;
}
int** spBasis(int maxE) {
int c;
int i, j, k, l;
int q = 0;
int** spStates;
spStates = (int**)malloc(330 * sizeof(int *));
for (c = 0; c < 330; c++) {
spStates[c] = malloc(4 * sizeof(int));
}
for (i = 0; i <= maxE; i++) {
for (j = i % 2; j <= i; j += 2) {
for (k = -(2 * j + 1); k <= (2 * j + 1); k += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j + 1;
spStates[q][3] = k;
q += 1;
}
for (l = -(2 * j - 1); l <= (2 * j - 1); l += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j - 1;
spStates[q][3] = l;
q += 1;
}
}
}
return spStates;
}
void mpBasis(int** spStates, int e, int maxE, int m, int M, int l,
int P, int * mpState, struct mpBasis *mpB, int position, int lastSpState) {
int i;
for (i = lastSpState; i < 330; i++) {
if (e > maxE) {
break;
} else if (position == 5) {
if (m == M && l % 2 == P) {
insertMpState(mpB, mpState);
break;
}
} else {
// add spState to mpState and make the recursive call for the next position
mpState[position] = i;
mpBasis(spStates, e + spStates[i][0], maxE, m + spStates[i][3], M,
l + spStates[i][1], P, mpState, mpB, position+1, i);
}
}
}
void initMpBasis(struct mpBasis *a, int initialSize, int sizeY) {
int c;
a->basis = (int **)malloc(initialSize * sizeof(int*));
for (c = 0; c < initialSize; c++) {
a->basis[c] = (int *) malloc(sizeY * sizeof(int));
}
a->size = 0;
a->capacity = initialSize;
}
void insertMpState(struct mpBasis *a, int* mpState) {
/*if (a->size == a->capacity) {
a->size *= 2;
a->basis = (int **)realloc(a->basis, a->size * sizeof(int));
}*/
a->basis[a->size++] = mpState;
}
Added all the code.
The problem is that after the recursive function has been called, the "basis" array in structure mpBasis still only contains random values, i.e. the mpBasis function hasn't done anything with it. Am I passing the mp argument by value here?
Thanks for your help!
The first step is to compile with warnings enabled. Eg if you are using GCC you can use option -Wall -Wextra.
EDIT:
(previous listing of >20 errors removed)
Ok, since you are using Visual Studio, enable warnings like this:
Open the project's Property Pages dialog box.
Select C/C++.
On the General property page, modify the Warning Level to /W4
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 8
#define POP 8
int answers[SIZE] = {5,3,1,7,4,6,0,2};
int getRand(int mod){
if (mod==0) return 0;
else return random()%mod;
}
void printArray(int array[]){
int i;
for(i=0; i<SIZE-1; i++) printf("(%i,%i),",i,array[i]);
printf("(%i,%i)",SIZE-1,array[SIZE-1]);
printf("\n");
}
int getWeight(int array[]){
int weight = 28;
int queen;
for(queen=0;queen<SIZE;queen++){ //for each queen
int nextqueen;
for(nextqueen=queen+1;nextqueen<SIZE;nextqueen++){ //for each of the other queens (nextqueen = queen to avoid counting pairs twice)
if(array[queen] == array[nextqueen] || abs(queen-nextqueen)==abs(array[queen]-array[nextqueen])){ //if conflict
weight--;
}
}
}
return weight;
}
void geneticAlgorithm(){
int population[POP][SIZE];
int children[POP][SIZE];
int weightProb[] = {};
int wpl = 0; //weightProb[] length
float mutProb = 0.05;
int done = 0;
int i;
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = getRand(SIZE);
while(done == 0){
for(i=0;i<POP;i++){
if(getWeight(children[i]) == 28){
printf("solution: ");
printArray(children[i]);
done = 1;
}
}
for(i=0;i<wpl;i++) weightProb[i] = (int)NULL; //clear weightprob
wpl=0;
//weighted probability distribution
for(i=0;i<POP;i++){
int w = getWeight(population[i]);
for(int j=0;j<w;j++){
weightProb[wpl] = i; //fill array with member number w times
wpl++;
}
}
//reproduce
for(i=0;i<POP;i+=2){
int par1 = weightProb[getRand(wpl)];
int par2 = weightProb[getRand(wpl)];
int split = getRand(SIZE);
//crossover
for(int j=0;j<split;j++){
children[i][j] = population[par1][j];
children[i+1][j] = population[par2][j];
}
for(int j=split;j<SIZE;j++){
children[i][j] = population[par2][j];
children[i+1][j] = population[par1][j];
}
//mutation
if(getRand(1000000)<=mutProb*1000000){
int child=getRand(2);
if(child == 0) children[i][getRand(SIZE)] = getRand(SIZE);
else children[i+1][getRand(SIZE)] = getRand(SIZE);
}
}
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = children[i][j];
wpl = 0;
}
}
int main(int argc, const char * argv[]){
srandom((unsigned int)time(NULL)); //seed random
geneticAlgorithm();
return 0;
}
when filling weightProb[], the population randomly changes.
i've debugged using print statements and it stops when wpl++ is commented out, but that is required
(wpl is the length of the weightProb array).
how is this happening?
This declaration:
int weightProb[] = {};
declares an empty array. This means each time you write to an element you write out of bounds of the array, and bad things will happen.
So I have two problems:
I'm using netbeans to code this.
The first is that the array value that I am setting in c.sArr is getting changed from 7 to some random number, and I can't figure out why.
The second is that when I try to run debug in netbeans, the code gives me a segfault, whereas when i run it normally it doesn't. It gives a segfault at the atoi function.
Whats going on here?
#include <stdio.h>
#include <stdlib.h>
#include "spoonMatrix.c"
int main(int argc, char** argv) {
int iterations;
int argCounter = 0;
int debug = 1;
int i,j,q;
if(argc < 2)
return -1;
if(debug == 1){
for(q=0;q<argc;q++)
printf("%s\n", argv[argCounter++]); //Checking the params
}
argCounter = 1;
iterations = atoi(argv[argCounter++]);
if(debug == 1)
printf("%d", iterations);
for(i=0;i<iterations;i++){
int rows = 0;
int columns = 0;
int m = 0, n, p, elemCount;
int posCount = 0;
int temp;
cm c;
c.row = rows;
c.column = columns;
c.elems = (char*)calloc(rows*columns, sizeof(char));
c.sArr = (int*)calloc(rows*columns, sizeof(int));
rows = atoi(argv[argCounter++]);
columns = atoi(argv[argCounter++]);
for(m=0;m<rows*columns;m++)
{
c.sArr[m] = -2;
//printf("Here");
}
if(debug == 1)
{
printf("Rows : Columns - %d : %d\n", rows, columns);
}
temp = argCounter;
printf("argCounter is: %d\n", argCounter);
for(elemCount = 0 ; argCounter < temp + rows; argCounter++)
{
for(n=0; n<columns; n++, elemCount++)
{
c.elems[elemCount] = argv[argCounter][n];
//if(debug == 1)
// printf("%c\t", c.elems[elemCount]);
if(c.elems[elemCount]== 's' || c.elems[elemCount] == 'S')
{
c.sArr[posCount] = elemCount;
printf("%c\t%d\t%d\t%d\n", c.elems[elemCount], elemCount, c.sArr[posCount++], posCount);
}
}
}
printf("%d\n", c.sArr[0]);
if(debug == 1)
{
for(j=0; j<rows*columns; j++)
{
printf("%c ", c.elems[j]);
}
printf("\n");
for(j=0;j<rows*columns;j++)
{
printf("%d ", c.sArr[j]);
}
}
}
return (EXIT_SUCCESS);
}
and
the other file is:
struct charMat{
int row;
int column;
char* elems;
int* sArr;
};
typedef struct charMat cm;
Coded in the hurry, excuse the weird debugging statements.
Thanks
You aren't allocating (enough) memory:
int rows = 0;
int columns = 0;
c.elems = (char*)calloc(rows*columns, sizeof(char)); // rows * columns is 0
c.sArr = (int*)calloc(rows*columns, sizeof(int)); // rows * columns is 0
rows = atoi(argv[argCounter++]);
columns = atoi(argv[argCounter++]);
From calloc:
If the size of the space requested is 0, the behavior is
implementation-defined: the value returned shall be either a null
pointer or a unique pointer.