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