1

I am writing a program in C and I am trying to create these structs. I have three of them:

  1. the first consisting of 2 ints and 2 chars,
  2. the second consisting of an int and an undefined array of pointers to the first one,
  3. and a third which contains 4 longs and 2 ints along with an undefined array of pointers to the second.

I am having trouble I believe with memory allocation for these structs when instantiated. Does anyone know what I am doing wrong (code below). Cache_Simulator is the main class and uses the others. Any help appreciated.

Directory_block.c

#include <stdio.h>
#include <stdlib.h>
#include "Directory_Block.h"
/* Created September, 15th, 2010;
 *
 *             Author: TJ, Cory
 */

 char containsData(directory_block* checkMe){
     return checkMe->valid;
 }
 void setValidOn(directory_block* checkMe){
     checkMe->valid = 1;
 }
 void setValidOff(directory_block* checkMe){
     checkMe->valid = 0;
 }
 char isOlder(directory_block* checkMe, int currentOldest){
    if(currentOldest < checkMe->LRU){
         return 1;
      }
     else{
         return 0;
     }
 }
 void setTag(directory_block* setMe, int tag){
     setMe->tag = tag;
 }
 char matchesTag(directory_block* checkMe, int theirTag){
     if(checkMe->tag == theirTag){
         return 1;
     }
     else{
         return 0;
     }
 }
 void incrementLRU(directory_block* incrementMe){
    incrementMe->LRU++;
 }

 void setLRU(directory_block* editMe, int LRUVal){
     editMe->LRU = LRUVal;
 }

cache_set* createSet(int setNumber,int numberOfBlocks,int printDetails){
     cache_set* newSet = malloc(sizeof(cache_set) + sizeof(directory_block)*numberOfBlocks);
 newSet->setNumber = setNumber;
 printf("Making Set %d\n",newSet->setNumber);
 int i = 0;
 for(; i < numberOfBlocks;i++)
 {
     printf("\tMaking Block #%d  ",i);
     if((i%4)==0&&i!=0)
     {
         printf("\n");
     }
     directory_block* block = malloc(sizeof(directory_block));
     newSet->blocks[i] = block;
     setValidOff(newSet->blocks[i]);
     setTag(newSet->blocks[i],setNumber);
     setLRU(newSet->blocks[i],-1);
     if(printDetails == 1)
     {
         printf("\tAddress %d\n",(int)newSet->blocks[i]);
         printf("\t\tValid=%d\n\t\tLRU=%d\n\t\tTag=%d\n",newSet->blocks[i]->valid
                 ,newSet->blocks[i]->LRU,newSet->blocks[i]->tag);
     }
 }
 printf("\n");
 return newSet;

 }

Directory_block.h

#ifndef DIRECTORY_BLOCK_H_
#define DIRECTORY_BLOCK_H_
#include "Directory_Block.h"
struct directory_block;
struct set;
struct cache;

typedef struct{
  int tag;
  int LRU;
  char valid;
  char offset;
}directory_block;

typedef struct{
int setNumber;
directory_block* blocks[];
}cache_set;

typedef struct{
int numberOfSets;
int linesPerSet;
long hits;
long misses;
long unknownAccesses;
long flushes;
cache_set* sets[];
}cache;


/*
 * params: checkMe - the line of the cache that we are checking
 * return: true = valid == 1; false valid == 0
 */
char containsData(directory_block* checkMe);
/*
 * functions: to set the valid bit to 1
 */
void setValidOn(directory_block* checkMe);
/*
 * functions: to set the valid bit to 0
 */
void setValidOff(directory_block* checkMe);
/*
 * params: currentOldest - the current oldest in directory_block*
 * return: the oldest current directory_block*
 */
char isOlder(directory_block* checkMe, int currentOldest);
/*
 * params: theirTag - the tag that is in the directory_block*
 * return: 0 if false; 1 is true
 */
char matchesTag(directory_block* checkMe, int theirTag);
/*
 * function: increments the value of the LRU in the block
 */
void incrementLRU(directory_block* incrementMe);
void setTag(directory_block* setMe, int tag);
/*
 * param: LRUVal - value to set to LRU to (negative means hasn't been used)
 */
void setLRU(directory_block* editMe,int LRUVal);
/*
 * param: numberOfBlocks number of blocks per set
 * creates a set and instantiates all directory blocks;
 * param: setNumber number of this set in the cache
 */
cache_set* createSet(int setNumber,int numberOfBlocks,int details);

#endif /* DIRECTORY_BLOCK_H_ */

Cache.c

#include "Directory_Block.h"
#include <stdio.h>
#include <stdlib.h>

directory_block* findLRU(cache* checkMe,int index){
int age;
age = 0;
int i = 0;
int oldest = 0;
for(; i < checkMe->numberOfSets;i++)
{
    if(isOlder(checkMe->sets[i]->blocks[index],age) == 1)
    {
        oldest = i;
        age = checkMe->sets[i]->blocks[index]->LRU;
    }
}
return checkMe->sets[i]->blocks[i];
}

int readInAddress(cache checkMe,char fileName[]){

return 0;
}

cache *makeCache(int numberOfLines,int numberOfSets,int details){

cache* returnMe = (cache*)malloc(sizeof(cache) + sizeof(int)*numberOfSets);
returnMe->numberOfSets = numberOfSets;
returnMe->linesPerSet = numberOfLines;
printf("Making Cache\n");
int i=1;
for(; i < returnMe->numberOfSets;i++){
    returnMe->sets[i] = createSet(i,returnMe->linesPerSet,details);
}
return returnMe;
}

void writeToCache(cache *addToMe,int address,int tag,int offset)
{
directory_block* LRUblock = findLRU(addToMe,address);
LRUblock->LRU = 0;
LRUblock->tag = tag;
LRUblock->valid = 1;
LRUblock->offset = offset;
}

char processAddress(cache checkMe,int address){

 return 0;
}

void reportCacheStatus(cache *reportMe){
int i = 0;
int j = 0;

for(;i < reportMe->numberOfSets;i++)
{

    printf("Set #%d\n",i);
    for(j=0;j < reportMe->linesPerSet;j++)
    {
        printf("\tBlock #%d - Tag=%d  Valid=%d  LRU=%d Offset=%d\n",j,reportMe->sets[i]->blocks[j]->tag
                ,reportMe->sets[i]->blocks[j]->valid,reportMe->sets[i]->blocks[j]->LRU
                ,reportMe->sets[i]->blocks[j]->offset);
    }
}

}

Cache.h

#include "Set.h"
#ifndef CACHE_H_
#define CACHE_H_

/*
 * params: checkMe - cache which that we will look for LRU at
 *            index - line index which we will check for LRU in all sets
 * return: setIndex - of the LRU block
 * function - iterates through sets and compares LRU value of directory_block at given
 *               index for each set.
 *
     */
int findLRU(cache checkMe,int index);

    /*
 * params: char [] - Name of File to read
 * return address struct contains access type and parsed address
    */
int readInAddress(cache checkMe,char[]);

/*
 *params: int cacheSize total bytes in cache, int linesPerSet number of blocks per set
 *params: int lineSize number of bytes per line
 * return int [] pointer with # of fields
 * (DEFINE FIELDS)
 */
cache* makeCache(int numberOfLines,int numberOfSets,int details);

/*
 * params: int address - perform cpu call for that address and see if there is a
 *  hit or miss or unknown access type - Update stats
 */
char processAddress(cache checkMe,int address);

void writeToCache(cache *addToMe,int address);

/*
 *Prints out display of information
 *For passes cache
 *Ex.
 *    INSERT EXAMPLE LINE
 */
void reportCacheStatus(cache* reportMe,int numberOfSets,int blocksPerSet);


#endif     /* CACHE_H_     */

Cache_simulator.c

#include <stdio.h>
#include <stdlib.h>
#include "fileParser.h"
#include "Directory_Block.h"
#include "Cache.h"
void setupCache(int details);
void performTrace(void);
void report(void);

int main(void)
{
printf("The Cache Simulator:\n\tJonathan Katon\n\tCory Brett\n\tThomas Pavlu\n");
setupCache(1);
//performTrace();
report();
return 0;
}

void setupCache(int details)
{
int numberOfLines = 1024/1;
int numberOfSets = numberOfLines/4;
numberOfLines = numberOfLines/numberOfSets;
printf("Number of Sets %d \nNumber of Lines Per Set %d\n",numberOfSets,numberOfLines);
printf("Cache Size %d,Cache_Set Size %d,Directory_block Size %d",sizeof(cache),sizeof(cache_set),sizeof(directory_block));
cache *instructionCache = makeCache(numberOfLines,numberOfSets,details);
//writeToCache(instructionCache,0);
reportCacheStatus(instructionCache,numberOfSets,numberOfLines);

}

void performTrace(void)
{
FILE* trace;
trace = fopen("trace.txt","r");
readNextMemoryAccess(trace);
}

void report(void)
{ // T.B.D
}

From an 'answer' by the OP about the question:

This was my attempt to try and fix a problem I was having with the memory at least i think I was. When I do a sizeof(cache_set) only it only returns a size large enough for everything but the array of pointers. This makes sense because the array isn't finite my question is how do I get around this issue? Any suggestions. Oh, and by the way, thanks for taking at look at this.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Thomas
  • 11
  • 2
  • Could you describe the actual problem you're having? This is just a bunch of code with no real problem description. – Greg Hewgill Sep 18 '10 at 21:47
  • 2
    Too, too much code man. Cut it down. Note that `cache` and `cache_set` both end on flexible length arrays. So someone (you?) will have to allocate an over-sized block that has room for the actual number of elements that will be stored in there. See also "struct hack" which has shown up on Stack Overflow several times in the last week. http://stackoverflow.com/questions/3711233/is-the-struct-hack-technically-undefined-behavior – dmckee --- ex-moderator kitten Sep 18 '10 at 21:47

1 Answers1

4

in Directory_block.c

cache_set* newSet = malloc(sizeof(cache_set) + sizeof(directory_block)*numberOfBlocks);

newSet is a pointer with space for:

  1. 1 cache_set: ok
  2. numberOfBlocks directory_blocks: huh?

This is wrong: cache_sets do not have directory_blocks in them; they have pointers to directory_blocks

typedef struct{
int setNumber;
directory_block* blocks[];
}cache_set;

I'd pay great attention to your type structure. Do you really need an array of pointers to directory_blocks inside cache_sets? If you do, the typedef is ok; if you don't, it's (probably) the code that's ok ... but, anyway, ... the structure and the malloc don't match.


Edit use the flexible array member

Suppose we have a struct with a flexible array member

struct Example {
    int value;
    double fam[]; /* fam is the flexible array, of doubles */
};

and now we want to use a variable of type struct Example with space for 100 doubles:

struct Example *example;
example = malloc(sizeof *example + 100 * sizeof *example->fam);
if (example) {
    /* use example, eg: */
    example->fam[42] = 3.14159265;
    /* and remember to free the allocated object when done */
    free(example);
}
pmg
  • 106,608
  • 13
  • 126
  • 198