Код 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 часов и не могу найти ошибку ...

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


person Buisson Magik    schedule 26.05.2015    source источник
comment
nextBloc=bloc+size+sizeof(Header); - вы знакомы с арифметикой указателей? Я подозреваю, что это проблема.   -  person user4520    schedule 26.05.2015
comment
Да, я думаю, что здесь тоже есть проблема, но как я могу сделать смещение? (Я хочу переместить указатель (size+sizeof(Header))...)   -  person Buisson Magik    schedule 26.05.2015
comment
Я думаю, что проблема в этой строке nextBloc=bloc+size+sizeof(Header);, поскольку nextBloc является указателем, а ваш nextblock должен быть равен ссылке блока &bloc+size+sizeof(Header);   -  person Vinay Shukla    schedule 26.05.2015
comment
@yanivx Это неправильно, &bloc будет struct Header**. Это С, а не С++.   -  person user4520    schedule 26.05.2015
comment
ОП: Пожалуйста, прочитайте об арифметике указателей в C. Короче говоря, если у вас есть указатель на какой-то тип и вы добавляете к нему X, указатель теперь указывает не на p + X, а на p + size_of_X_type * X; другими словами, если у вас есть int* p и его значение равно 0x1234, то p+1 равно 0x1238, а не 0x1235. nextBloc=bloc+size+sizeof(Header); заставляет nextBloc указывать на память далеко-далеко от того, что вы хотели, отсюда и нарушение прав доступа.   -  person user4520    schedule 26.05.2015
comment
Во-первых, если вы вызываете sbrk(), вы не можете использовать предоставленные системой вызовы malloc(). Я не вижу никаких доказательств того, что вы полностью заменили их. Во-вторых, как только вы полностью замените все вызовы всех подпрограмм malloc(), вы не сможете вызывать функции (такие как printf()), которые сами могут вызывать подпрограммы malloc().   -  person Andrew Henle    schedule 26.05.2015
comment
о, хорошо, как я могу перемещать указатель, я не понимаю, как я могу перемещать размер, который я хочу. Как это ? :` int tmp = size/sizeof(Header);nextBloc = bloc+tmp+1;//1, потому что заголовок — это тип блока.`   -  person Buisson Magik    schedule 26.05.2015


Ответы (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))
person LPeteR90    schedule 26.05.2015

person    schedule
comment
Пожалуйста, объясните свой ответ - person CoderPi; 23.11.2015