C-код для реализации моей собственной функции malloc

У меня проблема с моим 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

И я не понимаю, почему у меня есть segfault здесь:

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

Я нахожусь на этом в течение 2 часов и не могу найти ошибку...

если кто-то может мне помочь, это будет здорово. Благодарю.

2 ответа

szczurcio указал в комментариях:

Короче говоря, если у вас есть указатель на некоторый тип и вы добавляете к нему X, указатель теперь указывает не на p + X, но p + size_of_X_type * X;

Один из способов увеличить ваш указатель на количество байтов - это привести его к char* перед добавлением. Чтобы избежать предупреждений компилятора, вы также должны привести char* вернуться к Header*, Вместо

nextBloc = bloc + size + sizeof(Header);

Вы могли бы написать:

nextBloc = (Header*) (((char*) bloc) + size + sizeof(Header))
#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 stackru */
/* http://stackru.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);
}
Другие вопросы по тегам