自定义malloc,分段错误

自定义malloc,分段错误,c,memory,memory-management,malloc,C,Memory,Memory Management,Malloc,我正在做一个定制的malloc。我做了一个非常简单的操作,但现在我正在尝试合并和拆分块,以提高对sbrk()的调用效率。当我尝试用不多的malloc执行自定义程序时,它工作得非常好。但是,在一些成功的分配之后,只要我尝试更多的malloc或例如命令ls,调用split函数时就会出现奇怪的分段错误(内核转储) 任何帮助或暗示都将不胜感激 #include <stdio.h> #include <string.h> #include <stdlib.h> #inc

我正在做一个定制的malloc。我做了一个非常简单的操作,但现在我正在尝试合并和拆分块,以提高对
sbrk()
的调用效率。当我尝试用不多的malloc执行自定义程序时,它工作得非常好。但是,在一些成功的分配之后,只要我尝试更多的malloc或例如命令
ls
,调用split函数时就会出现奇怪的分段错误(内核转储)

任何帮助或暗示都将不胜感激

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include "struct.h"

static p_meta_data first_element = NULL;
static p_meta_data last_element  = NULL;

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

#define ALIGN8(x) (((((x)-1)>>3)<<3)+8)
#define MAGIC     0x87654321

void *malloc(size_t size_bytes);
p_meta_data search_available_space(size_t size_bytes);
p_meta_data request_space(size_t size_bytes);
p_meta_data merge(p_meta_data meta_data1, p_meta_data meta_data2);
void split(p_meta_data meta_data, size_t size_bytes);
void free(void *ptr);
void *calloc(size_t num_bytes, size_t num_blocs);
void *realloc(void *ptr, size_t size_bytes);

p_meta_data search_available_space(size_t size_bytes) {
    p_meta_data current = first_element; 
    while (current && !(current->available && current->size_bytes >= size_bytes)){
        fprintf(stderr, " %zu libre %d\n", current->size_bytes, current->available);
        current = current->next;
    }
    if (current == NULL) {
        fprintf(stderr, "null\n" );
    } else {
        fprintf(stderr, "%zu libre %d\n", current->size_bytes, current->available);
    }
    return current;
}

p_meta_data request_space(size_t size_bytes) {
    if (size_bytes < 122880) {
        size_bytes = 122880;
        fprintf(stderr, "request %zu\n", size_bytes);
    }
    p_meta_data meta_data;

    meta_data = (void *)sbrk(0);
    if (sbrk(SIZE_META_DATA + size_bytes) == (void *)-1)
        return (NULL);

    meta_data->size_bytes = size_bytes;
    meta_data->available = 0;
    meta_data->magic = MAGIC;
    meta_data->next = NULL;
    meta_data->previous = NULL;
    return meta_data;
}

p_meta_data merge(p_meta_data meta_data1, p_meta_data meta_data2) {
    if (!meta_data1 || !meta_data2) {
        return NULL;
    }

    meta_data1->size_bytes = meta_data1->size_bytes + SIZE_META_DATA + meta_data2->size_bytes;
    meta_data1->next = meta_data2->next;
    if (last_element == meta_data2) {
        fprintf(stderr, "gleich\n");
        last_element = meta_data1;
    }
    meta_data2 = NULL;

    return meta_data1;
}

void free(void *ptr) {
    p_meta_data meta_data;

    if (!ptr)
        return;

    pthread_mutex_lock(&mutex);

    meta_data = (p_meta_data)(ptr - SIZE_META_DATA);

    if (meta_data->magic != MAGIC) {
        fprintf(stderr, "ERROR free: value of magic not valid\n");
        exit(1);
    }

    meta_data->available = 1;
    fprintf(stderr, "Free at %x: %zu bytes\n", meta_data, meta_data->size_bytes);

    p_meta_data meta_data_prev, meta_data_next;
    meta_data_prev = meta_data->previous;
    meta_data_next = meta_data->next;

    if (meta_data_prev && meta_data_prev->available) {
        meta_data = merge(meta_data_prev, meta_data);
    }
    if (meta_data_next && meta_data_next->available) {
        meta_data = merge(meta_data, meta_data_next);
    }

    pthread_mutex_unlock(&mutex);
}

void split(p_meta_data meta_data, size_t size_bytes) {
    if (!meta_data) {
        fprintf(stderr, "no deberia entrar\n");
        return;
    }
    p_meta_data meta_data2;

    size_t offset = SIZE_META_DATA + size_bytes;

    meta_data2 = (p_meta_data)(meta_data + offset);

    fprintf(stderr, "size of metadata %d", meta_data->size_bytes - size_bytes - SIZE_META_DATA);

    meta_data2->size_bytes = meta_data->size_bytes - size_bytes - SIZE_META_DATA;
    meta_data2->available = 1;
    meta_data2->magic = MAGIC;
    meta_data2->previous = meta_data;
    meta_data2->next = meta_data->next;

    if (meta_data == last_element) {
        last_element = meta_data2;
    }

    meta_data->size_bytes = size_bytes;
    meta_data->next = meta_data2;

    return;
}

void *malloc(size_t size_bytes) {
    void *p, *ptr;
    p_meta_data meta_data;

    if (size_bytes <= 0) {
        return NULL;
    }

    size_bytes = ALIGN8(size_bytes);
    fprintf(stderr, "Malloc %zu bytes\n", size_bytes);

    // Bloquegem perque nomes hi pugui entrar un fil
    pthread_mutex_lock(&mutex);

    meta_data = search_available_space(size_bytes);

    if (meta_data) { // free block found
        fprintf(stderr, "FREE BLOCK FOUND---------------------------------------------------\n");
        meta_data->available = 0; //reservamos el bloque
    } else {     // no free block found
        meta_data = request_space(size_bytes); //pedimos más espacio del sistema
        if (!meta_data) //si meta_data es NULL (es decir, sbrk ha fallado)
            return (NULL);

        if (last_element) // we add the new block after the last element of the list
            last_element->next = meta_data;
        meta_data->previous = last_element;
        last_element = meta_data;

        if (first_element == NULL) // Is this the first element ?
            first_element = meta_data;
    }

    fprintf(stderr, "die differenz %zu\n", meta_data->size_bytes - size_bytes);
    if ((meta_data->size_bytes - size_bytes) > 12288) {
        split(meta_data, size_bytes);
        fprintf(stderr,"call split\n");
    }

    p = (void *)meta_data;

    // Desbloquegem aqui perque altres fils puguin entrar
    // a la funcio
    pthread_mutex_unlock(&mutex);

    // Retornem a l'usuari l'espai que podra fer servir.
    ptr = p + SIZE_META_DATA; //p es puntero al inicio de meta_data, y ptr es el puntero al inicio del bloque de datos en sí (justo después de los metadatos)
    return ptr;
}

void *calloc(size_t num_bytes, size_t num_blocs) {
    size_t mem_to_get = num_bytes * num_blocs;
    void *ptr = malloc(mem_to_get);
    if (ptr == NULL) {
        return ptr;
    } else {
        memset(ptr, 0, mem_to_get);
        return ptr;
    }
}

void *realloc(void *ptr, size_t size_bytes) {
    fprintf(stderr, "realloc\n");
    if (ptr == NULL) {
        return malloc(size_bytes);
    } else {
        p_meta_data inic_bloc = (p_meta_data )(ptr - SIZE_META_DATA);
        if (inic_bloc->size_bytes >= size_bytes) {
            return ptr;
        } else {
            void *new_p = malloc(size_bytes);
            memcpy(new_p, ptr, inic_bloc->size_bytes);
            inic_bloc->available = 1;
            return new_p;
        }
    }
}
#包括
#包括
#包括
#包括
#包括“struct.h”
静态p_meta_data first_element=NULL;
静态p_元数据最后一个元素=NULL;
静态pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
#定义ALIGN8(x)(((x)-1)>>3)size\u bytes>=大小\u字节)){
fprintf(标准字符,“%zu libre%d\n”,当前->大小\字节,当前->可用);
当前=当前->下一步;
}
如果(当前==NULL){
fprintf(stderr,“null\n”);
}否则{
fprintf(标准字符,“%zu libre%d\n”,当前->大小\字节,当前->可用);
}
回流;
}
p_元数据请求空间(大小字节){
如果(大小_字节<122880){
大小_字节=122880;
fprintf(stderr,“请求%zu\n”,大小\u字节);
}
p_元数据元数据;
元数据=(void*)sbrk(0);
if(sbrk(大小元数据+大小字节)==(void*)-1)
返回(空);
元数据->大小字节=大小字节;
元数据->可用=0;
元数据->魔术=魔术;
元数据->下一步=空;
元数据->上一个=空;
返回元数据;
}
p_元数据合并(p_元数据元数据元数据1,p_元数据元数据元数据2){
如果(!meta_data1 | |!meta_data2){
返回NULL;
}
meta_data1->size_bytes=meta_data1->size_bytes+size_meta_DATA+meta_data2->size_bytes;
meta_data1->next=meta_data2->next;
if(最后一个元素==元数据2){
fprintf(标准术语,gleich\n);
最后一个元素=元数据1;
}
meta_data2=NULL;
返回元数据1;
}
无空隙(空隙*ptr){
p_元数据元数据;
如果(!ptr)
返回;
pthread_mutex_lock(&mutex);
元数据=(p_元数据)(ptr-大小元数据);
如果(元数据->魔术!=魔术){
fprintf(stderr,“无错误:magic的值无效\n”);
出口(1);
}
元数据->可用=1;
fprintf(标准,“在%x时可用:%zu字节\n”,元数据,元数据->大小字节);
p_meta_data meta_data_prev,meta_data_next;
meta_data_prev=meta_data->previous;
元数据下一步=元数据->下一步;
如果(元数据上一版本和元数据上一版本->可用){
元数据=合并(元数据之前,元数据);
}
如果(元数据下一步和元数据下一步->可用){
元数据=合并(元数据,元数据下一步);
}
pthread_mutex_unlock(&mutex);
}
void split(p_meta_data meta_data,size_t size_字节){
如果(!元数据){
fprintf(标准,“无德贝里亚夹带”);
返回;
}
p_元数据meta_data2;
大小偏移量=大小元数据+大小字节;
元数据2=(p_元数据)(元数据+偏移量);
fprintf(stderr,“元数据大小%d”,元数据->大小字节-大小字节-大小元数据);
元数据2->size\u bytes=meta\u data->size\u bytes-size\u bytes-size\u元数据;
元数据2->available=1;
meta_data2->magic=magic;
元数据2->previous=元数据;
元数据2->next=元数据->next;
if(元数据==最后一个元素){
最后一个元素=元数据2;
}
元数据->大小字节=大小字节;
元数据->下一步=元数据2;
返回;
}
void*malloc(大小\u t大小\u字节){
无效*p,*ptr;
p_元数据元数据;
if(size_bytes available=0;//reservamos el bloque
}else{//未找到可用块
元数据=请求空间(大小字节);//pedimos más espacio del sistema
if(!meta_data)//si meta_data es NULL(es decir,sbrk ha fallado)
返回(空);
if(last_element)//我们在列表的最后一个元素之后添加新块
最后一个元素->下一个=元数据;
元数据->上一个=最后一个元素;
最后一个元素=元数据;
if(first_element==NULL)//这是第一个元素吗?
第一个元素=元数据;
}
fprintf(标准,“die differencez%zu\n”,元数据->大小字节-大小字节);
如果((元数据->大小字节-大小字节)>12288){
拆分(元数据,大小为字节);
fprintf(stderr,“调用拆分\n”);
}
p=(void*)元数据;
//这是一个很好的选择
//拉芬西奥酒店
pthread_mutex_unlock(&mutex);
//你可以用一个普通人的名字来称呼我。
ptr=p+SIZE_META_DATA;//p是META_DATA的一部分,y ptr是sín datos的一部分(仅限于metadatos的数据)
返回ptr;
}
void*calloc(大小\u t数量\u字节,大小\u t数量\u块){
size_t mem_to_get=num_bytes*num_blocs;
void*ptr=malloc(mem-to-get);
如果(ptr==NULL){
返回ptr;
}否则{
memset(ptr,0,mem_to_get);
返回ptr;
}
}
void*realloc(void*ptr,大小字节){
fprintf(标准,“realloc\n”);
如果(ptr==NULL){
返回malloc(大小_字节);
}否则{
p_meta_data inic_bloc=(p_meta_data)(ptr-SIZE_meta_data);
如果(inic\u bloc->size\u bytes>=size\u bytes){
返回ptr;
}否则{
void*new\u p=malloc(大小\u字节);
memcpy(新建、ptr、inic\u块->大小\u字节);
inic_bloc->available=1;
返回新的\u p;
}
}
}
其中,struct.h是:

#include <stddef.h>
#include <unistd.h>

#define SIZE_META_DATA  sizeof(struct m_meta_data)
typedef struct m_meta_data *p_meta_data;

/* This structure has a size multiple of 8 */

struct m_meta_data {
    size_t  size_bytes;
    int     available;
    int     magic;
    p_meta_data next;
    p_meta_data previous;
};
#包括
#包括
#定义大小元数据大小(结构元数据)
类型定义结构m_元数据*p_元数据;
/*此结构的大小是8的倍数*/
结构m_元数据{
大小\u t大小\u字节;
int可用;
智力魔术;
p_meta_data next;
p_元数据先前;
};

以下是关于你的一些评论
meta_data2 = (p_meta_data)((unsigned char *)meta_data + offset);
char *strdup(const char *s) {
    size_t len = strlen(s);
    char *p = malloc(len + 1);
    if (p) {
        memcpy(p, s, len + 1);
    }
    return p;
}

char *strndup(const char *s, size_t n) {
    size_t len;
    char *p;

    for (len = 0; len < n && s[n]; len++)
        continue;
    if ((p = malloc(len + 1)) != NULL) {
        memcpy(p, s, len);
        p[len] = '\0';
    }
    return p;
}
p_meta_data inic_bloc = (p_meta_data)ptr - 1;