【问题标题】:C code for implementing my own malloc function用于实现我自己的 malloc 函数的 C 代码
【发布时间】:2015-05-26 12:51:59
【问题描述】:

我的 C 代码有问题。我必须做一个 malloc 函数。首先是我的代码:

#include <stdio.h>
#include <unistd.h>
#include "my-malloc.h"
#define MOST_RESTRICTING_TYPE double
// Pour s’aligner sur des frontieres multiples
// de la taille du type le plus contraignant
typedef union header {// Header de bloc
    struct{
        unsigned int size; // Taille du bloc
        union header *ptr;// bloc libre suivant
    } info;
    MOST_RESTRICTING_TYPE dummy;// Ne sert qu’a provoquer un alignement
} Header;


/* Une version de my-malloc.c qu'il faudra vite remplacer par quelque chose de
 * plus "raisonnable". Ce code n'est juste là que pour pouvoir lancer
 * les programmes de test.
 */
static int nb_alloc   = 0;      /* Nombre de fois où on alloué     */
static int nb_dealloc = 0;      /* Nombre de fois où on désalloué  */
static int nb_sbrk    = 0;      /* nombre de fois où a appelé sbrk */
static Header sentinelle;

void *mymalloc(size_t size) {
    int sbrkUsage=0;
    static Header *bloc;
    static Header *nextBloc;
    nb_alloc += 1;
    printf("mymalloc(%zu)\n",size);
    if(bloc==NULL){     
        bloc=&sentinelle;
        sentinelle.info.size=0;
        sentinelle.info.ptr=bloc;
    }

    Header *ptr = &sentinelle;
    Header *ptr_prec = &sentinelle;
    while((ptr=ptr->info.ptr)!=&sentinelle){        
        ptr_prec=ptr;
        if(ptr->info.size >= (size+sizeof(Header)))
            break;      
    }

    if(ptr==&sentinelle){
        if((bloc=sbrk(800))==(void *)-1){
            printf("ERREUR\n");
        }
        nb_sbrk++;
        printf("\t-->sbrk(800)\n");
        sbrkUsage=1;
        bloc->info.size=800;
        bloc->info.ptr=&sentinelle;
        ptr_prec->info.ptr=bloc;
    }


    if(sbrkUsage==0){
        bloc->info.size=size+sizeof(Header);    
        nextBloc=bloc+size+sizeof(Header);
        nextBloc->info.size=((ptr->info.size)-(size+sizeof(Header)));
    }
    else{
        nextBloc=bloc+size+sizeof(Header);
        printf("PASSE ? %zu\n",800-(size+sizeof(Header)));
        nextBloc->info.size=((800)-(size+sizeof(Header)));
        printf("PASSE ? %zu\n",800-(size+sizeof(Header)));
    }

    printf("sizeptr : %d\n",ptr->info.size);
    nextBloc->info.ptr=&sentinelle;
    ptr_prec->info.ptr=nextBloc;
    bloc->info.ptr=nextBloc;
    sentinelle.info.ptr=nextBloc;

    //printf("returned : %p\n",&bloc);      
    return bloc;
}


void myfree(void *ptr) {
  nb_dealloc += 1;
  free(ptr);
}

void *mycalloc(size_t nmemb, size_t size) {
  nb_alloc += 1;
  return calloc(nmemb, size);
}

void *myrealloc(void *ptr, size_t size) {
  /* il faudrait probablement changer les valeur de nballoc et
   * nb_dealloc dans une véritable implémentation 
   */
  return realloc(ptr, size);
}

#ifdef MALLOC_DBG
void mymalloc_infos(char *msg) {
  if (msg) fprintf(stderr, "**********\n*** %s\n", msg);

  fprintf(stderr, "# allocs = %3d - # deallocs = %3d - # sbrk = %3d\n",
      nb_alloc, nb_dealloc, nb_sbrk);
  /* Ca pourrait être pas mal d'afficher ici les blocs dans la liste libre */

  if (msg) fprintf(stderr, "**********\n\n");
}
#endif

我不明白为什么我在这里有段错误:

printf("PASSE ? %zu\n",800-(size+sizeof(Header)));
nextBloc->info.size=((800)-(size+sizeof(Header)));
printf("PASSE ? %zu\n",800-(size+sizeof(Header)));

我用了 2 个小时,找不到错误...

如果有人可以帮助我,那就太好了。谢谢。

【问题讨论】:

  • nextBloc=bloc+size+sizeof(Header); - 你知道指针算法吗?我怀疑这是问题所在。
  • 是的,我认为这里也有问题,但我该如何进行偏移? (我想移动(size+sizeof(Header))的指针...)
  • 我认为问题出在nextBloc=bloc+size+sizeof(Header); 这一行,因为nextBloc 是一个指针,您的nextblock 应该等于集团&amp;bloc+size+sizeof(Header); 的引用
  • @yanivx 错了,&amp;bloc 将是 struct Header**。这是 C,不是 C++。
  • OP:请阅读 C 中的指针运算。简而言之,如果您有一个指向某种类型的指针,并且您将 X 添加到它,那么指针现在指向的不是p + X,而是p + size_of_X_type * X ;换句话说,如果你有int* p 并且它的值是0x1234,那么p+1 等于0x1238,而不是0x1235nextBloc=bloc+size+sizeof(Header); 使 nextBloc 指向内存,远离你想要的,因此访问冲突。

标签: c malloc sbrk


【解决方案1】:

szczurcio在cmets中指出:

简而言之,如果你有一个指向某个类型的指针,并且你给它添加了 X,那么指针现在指向的不是p + X,而是p + size_of_X_type * X

将指针增加多个字节的一种方法是在添加之前将其转换为char*。为避免编译器警告,您还应该将char* 转换回Header*。而不是

nextBloc = bloc + size + sizeof(Header);

你可以写:

nextBloc = (Header*) (((char*) bloc) + size + sizeof(Header))

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    /**
    this is my code I used for class project
    */
    static unsigned char mySpace[1024 * 1024]; //reserve 1 MB for malloc
    static size_t next_index = 0;
    int mySize = 0;
    int allocated=0;
    int myCount =0;
    int free=0;
    int largestFreeSpace=0;
     int freeByte = 0xFF;
    int posistion;
    void hexDump (char *desc, void *addr, int len) ;
    // my malloc to process requested space.
    unsigned char * myMalloc(int size)
    {
        printf("Looking for size %d\n",size);
        int flag=0;
        int flagPosition,j;
        int numOfFreeBytes=0;
        int left=0;
         for(j=0; j<myCount; j++){// looping over each byte
            if(flag){// flag bit found
                if(mySpace[j]==0x00){
                    numOfFreeBytes++;// increment number of open space
                    if(numOfFreeBytes==(size+1)){
                        int x=myCount-(flagPosition+size+1) ;
                        mySpace[flagPosition]=size+1;
                        mySpace[flagPosition+size+1]=0x80|x; //set flag
                        freeByte= 0x80|x;// new flag hex
                        left=(myCount/8)-flagPosition;
                        allocated+= size+1;// count allocated
                        posistion=flagPosition+size+1;// flag position
                        return &mySpace[flagPosition];// return
                        }
                }
            }
            // if we find a flag
            if(mySpace[j]==freeByte){
                flag=1;
                flagPosition=j;
                numOfFreeBytes=0;
    
            }
        }
    }
    // free malloc of space previously allocated
    void myFree(unsigned char * buffer)
    {
       int j,i;
       int flag=0;//
       int x=* buffer;// size to give back
         for(j=0; j<myCount; j++){
             if(mySpace[j]==*buffer){// if requested is true
                mySpace[j]=0x80|*buffer;//set value of the space to segments
                flag=1;
            }
        }
        // know when to give memory back
        if(flag==1){
        allocated=allocated-x;
        }
    }
    /* space is a pointer to space you have allocated
    */
    void init(unsigned char * space, int size, int count)
    {   mySize =size;// my  whole size  of malloc
        myCount=count;//my whole count
        int i;
        for(i=0;i<size;i++){
            space[count*i]=0x80|(count);// set the initial value to 0xff
        }
    }
    /* return how much space is allocated, in bytes not blocks */
    
    int totalAllocated()
    {
      return allocated;  /* return allocated space */
    }
    
    /* return how much space is free, in bytes not blocks */
    int  totalFree()
    {
    return myCount-allocated;/* return unallocated  */
    
    }
    /* this routine should return the largest buffer available */
    //largestFreeSpace
    int largestAvailable()
    {   int j;
        int large=0x00;//initialize
         for(j=0; j<myCount; j++){
             if(mySpace[j]!=0xaa && (mySpace[j]!=mySpace[posistion])){//ignore flag and 0's
                if(mySpace[j]>0){
                    if(mySpace[j]>large){
                     large=mySpace[j];//set large as current
                    }
                }
             }
        }
      return large-0x80;  //return the largest fragment
    }
    /* return the size in bytes of the smallest buffer available */
    int smallestAvailable()
    {
    int j;
        int small=mySpace[0];//initialize small
         for(j=0; j<myCount; j++){
             if(mySpace[j]!=0xaa && (mySpace[j]!=mySpace[posistion])){
                if((mySpace[j]-0x80>-1)){ //don't check allocated space
                    if(mySpace[j]>0){// make sure space is a segment
                        if(mySpace[j]<small){
                            small=mySpace[j];//set new smallest
                        }
                    }
                }
             }
        }
      return small-0x80;//return the smallest
    }
    
    
    
    
    // main
    int main(int argc, char * argv[])
    {
      unsigned char * ptr, *ptr2, *ptr3, *ptr4;
    
      printf("Init \n");
    // initialize
      init(mySpace, 1, 127);
    
      hexDump ("my buf",mySpace, 0x20 );
    
      ptr = myMalloc(3);
    
      hexDump ("my buf",mySpace, 0x20 );
    
      ptr2 = myMalloc(1);
    
      hexDump ("my buf",mySpace, 0x20 );
    
      ptr3= myMalloc(4);
    
      hexDump ("my buf",mySpace, 0x20 );
    
    
      hexDump ("my buf",mySpace, 0x20 );
    
      printf("Total allocated %d \n", totalAllocated() * 1);
    
      printf("Total free %d \n", totalFree() *1);
    
      myFree(ptr);
    
      myFree(ptr2);
    
      myFree(ptr3);
      hexDump ("my buf",mySpace, 0x20 );
    
      printf("Total allocated %d \n", totalAllocated() * 1);
    
      printf("Total free %d \n", totalFree() *1);
    
      hexDump ("my buf",mySpace, 0x20 );
      printf("\nLargest Fragmentation  has : %x \n",largestAvailable());
      printf("\nSmallest Fragmentation  has : %x \n",smallestAvailable());
    
    }
    
    /* thank you stackoverflow */
    /* http://stackoverflow.com/questions/7775991/how-to-get-hexdump-of-a-structure-data */
    void hexDump (char *desc, void *addr, int len)
    {
        int i;
        unsigned char buff[17];
        unsigned char *pc = (unsigned char*)addr;
        // Output description if given.
        if (desc != NULL)
            printf ("%s:\n", desc);
        // Process every byte in the data.
        for (i = 0; i < len; i++) {
            // Multiple of 16 means new line (with line offset).
            if ((i % 16) == 0) {
                // Just don't print ASCII for the zeroth line.
                if (i != 0)
                printf ("  %s\n", buff);
                // Output the offset.
                printf ("  %04x ", i);
            }
            // Now the hex code for the specific character.
            if(pc[i]==00){
              pc[i]=0xaa;
                      printf (" %02x", pc[i]);
    
            }else{
            printf (" %02x", pc[i]);
            }
            // And store a printable ASCII character for later.
            if ((pc[i] < 0x20) || (pc[i] > 0x7e))
                buff[i % 16] = '.';
            else
                buff[i % 16] = pc[i];
            buff[(i % 16) + 1] = '\0';
        }
        // Pad out last line if not exactly 16 characters.
        while ((i % 16) != 0) {
            printf ("   ");
            i++;
        }
        // And print the final ASCII bit.
        printf ("  %s\n", buff);
    }
    

    【讨论】:

    • 请解释一下你的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    相关资源
    最近更新 更多