分段故障分配功能结果

时间:2017-08-24 11:13:52

标签: c++ memory memory-management segmentation-fault

我正在尝试编写内存分配接口。将 new_buf_addr myalloc 函数返回到main并将其分配给变量 temp ,在gdb中检查时,会出现Seg错误。返回值不是指向本地值的指针,所以我想这不是问题。我试图返回其他类型,但结果相同

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>


void* HEAD = NULL;
void* NULLPTR = (void*)10;
std::size_t ATTRS_SIZE = 2*sizeof(NULL) + sizeof(std::size_t) + sizeof(char);

// BUFFER STRUCT
// |--prev--|--next--|--size--|--flag--|–––––––––––data–––––––––––|
// |---8b---|---8b---|---8b---|---1b---|
// |---------------25b-----------------|––––––––size - 25b––––––––|
// flag:
// 0 - busy
// 1 - free


// add metadata
void init_buf(void *buf, std::size_t size, void *prev, void *next, char free_flag ){
    printf("%d\n", sizeof(prev) );
    memcpy(buf, prev, sizeof(prev));
    memcpy(buf + sizeof(NULL), next, sizeof(next));
    memcpy(buf + 2*sizeof(NULL), &size, sizeof(std::size_t));
    memcpy(buf + 2*sizeof(NULL) + sizeof(std::size_t), &free_flag, sizeof(char));
}


// setups buffer where memory will be allocated
void mysetup(void *buf, std::size_t size)
{
    HEAD = buf;
    init_buf(buf, size, &NULLPTR, &NULLPTR, 1);
}

void* myalloc(std::size_t size)
{
    void* buf = HEAD;
    while (true) {
        // getting buf attrs
        void* prev;
        void* next;
        std::size_t* buf_size;
        char free_flag;

        printf("%d %d %d\n", sizeof(buf), sizeof(void*), sizeof(prev));
        // memcpy(prev, buf, sizeof(void*));
        prev = buf;
        // memcpy(next, buf + sizeof(NULL), sizeof(void*));
        next = buf + sizeof(NULL);
        memcpy(buf_size, buf + 2*sizeof(NULL) , sizeof(std::size_t));
        memcpy(&free_flag, buf + 2*sizeof(NULL) + sizeof(std::size_t), sizeof(char));

        // check if buf is free and big enough to allocate
        if (size < *buf_size && free_flag){
            void* new_buf_addr = buf + *buf_size - ATTRS_SIZE - size;

            // point buf's next to new buf
            memcpy(next, new_buf_addr, sizeof(new_buf_addr));
            init_buf(new_buf_addr, size, buf, &NULLPTR, 0);

            new_buf_addr = new_buf_addr + ATTRS_SIZE;
            return new_buf_addr;
        }
        // going to next buf
        else {
            if (next == &NULLPTR) {
                printf("%s\n", "Can't allocate memory");
                return NULL;
            }
            else {
                buf = next;
            }
        }
    }
}

void myfree(void *p)
{
    while (true){
        void *left_neighbor;
        memcpy(left_neighbor, p - ATTRS_SIZE, sizeof(void*));
        void *right_neighbor;
        memcpy(right_neighbor, p - ATTRS_SIZE + sizeof(void*), sizeof(void*));
        std::size_t* size;
        memcpy(size, p - ATTRS_SIZE + 2 * sizeof(void*) , sizeof(std::size_t));
        char* free_flag;
        memcpy(free_flag, p - sizeof(char), sizeof(char));

        bool is_right = false;
        if (right_neighbor != &NULLPTR) {
            bool right_is_free = *((char*)(right_neighbor + ATTRS_SIZE - sizeof(char))) == 1;
            if (right_is_free) {
                is_right = true;
            }
        }

        bool is_left = false;
        if (left_neighbor != &NULLPTR) {
            bool left_is_free = *((char*)(right_neighbor + ATTRS_SIZE - sizeof(char))) == 1;
            if (left_is_free) {
                is_left = true;
            }
        }



        if (is_right) {
            memcpy(size, p - ATTRS_SIZE + 2 * sizeof(void*) , sizeof(std::size_t));
            void* right_next;
            std::size_t* right_size;
            memcpy(right_next,  right_neighbor + sizeof(void*), sizeof(void*));
            memcpy(right_size,  right_neighbor + 2 * sizeof(void*), sizeof(std::size_t));

            // set p->next to right_neighbor's next
            memcpy(right_neighbor, right_next, sizeof(void*));
            // adding right_neighbor->size to p->size
            *size = *size + *right_size;
        }
        else if (is_left){
            memcpy(left_neighbor +  sizeof(void*), right_neighbor, sizeof(void*));

            std::size_t* new_size;
            // set left_neighbor->next to p->next
            memcpy(new_size, left_neighbor +  2 * sizeof(void*), sizeof(std::size_t));
            //adding p->size to left_neighbor->size
            *new_size = *new_size + *size;
            // pointig p to data to keep cycle alive
            p = left_neighbor + ATTRS_SIZE;
        }
        else {
            // Just in case if is 0 set it to 1
            char flag = 1;
            memcpy(p - sizeof(char), &flag, sizeof(char));
            return;
        }
    }
}

int main() {
    void* ret[10];
    std::size_t buf_size = 100*1024;
    void* buf = malloc(buf_size);
    mysetup(buf, buf_size);
    std::size_t block_size = 16;
    int i = 0;
    while(1) {
        void* temp = myalloc(block_size);
        ret[i] = temp;
        if(ret[i] == NULL) break;
        i++;
    }
    for(int j = 0; j < i; j++) {
        std::size_t rnd = (rand()/(double)RAND_MAX*(i-1));
        void* swp = ret[rnd];
        ret[rnd] = ret[j];
        ret[j] = swp;
    }
    for(int j = 0; j < i; j++) {
        myfree(ret[j]);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:0)

好的,看看稀疏的评论,“8b”表示“8字节”,看起来像是你计划从sizeof(NULL)获得的指针大小。而std::size_t意味着你正在编译C ++。

在C ++中,NULL 不是指针sizeof(NULL)可以小于或大于sizeof(void*)。我希望您的系统#define NULL 0sizeof(NULL)==4。不是8个字节。

答案 1 :(得分:0)

问题在于void* prevvoid* next应为void**,因为 prev next 是指向另一个缓冲区,也是指针

相关问题