C编程 - Malloc Structs和未定义的数组

时间:2010-09-18 21:43:25

标签: c arrays pointers malloc struct

我正在用C编写程序,我正在尝试创建这些结构。 我有三个:

  1. 第一个由2个整数和2个字符组成,
  2. 第二个包含int和未定义的第一个指针数组
  3. 和第三个包含4个long和2个int以及指向第二个的未定义指针数组。
  4. 我遇到麻烦我相信在实例化时这些结构的内存分配。有谁知道我做错了什么(下面的代码)。 Cache_Simulator是主类,并使用其他类。任何帮助表示赞赏。

    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
    }
    

    OP的'答案'是关于这个问题:

      

    这是我试图尝试解决我在记忆中遇到的问题,至少我认为我是。当我执行sizeof(cache_set)时,它只会返回一个足够大的大小,除了指针数组之外的所有内容。这是有道理的,因为数组不是有限的我的问题是我如何解决这个问题?有什么建议。哦,顺便说一下,谢谢你看看这个。

1 个答案:

答案 0 :(得分:4)

Directory_block.c中的

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

newSet是一个带空格的指针:

  1. 1 cache_set:ok
  2. numberOfBlocks directory_blocks:呵呵?
  3. 这是错误的:cache_sets中没有directory_blocks;他们有pointers to directory_blocks

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

    我会非常注意你的类型结构。你真的需要一个指向cache_sets内的directory_blocks的指针数组吗?如果你这样做,typedef就可以了;如果你不这样做,那么(可能)代码就可以了......但是,无论如何,...结构和malloc不匹配。


    编辑使用灵活的数组成员

    假设我们有一个带有灵活数组成员的结构

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

    现在我们想要使用struct Example类型的变量,空间为100个双倍:

    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);
    }