简体   繁体   English

malloc 对齐内存 C

[英]malloc align memory C

I have to recode malloc , free and realloc for a school project.我必须为学校项目重新编码mallocfreerealloc

I done every function but when I try to do ls -lRa /home or cat or gcc I got a segmentation fault after a while of execution... I tried to search the error with valgrind but I don't understand the errors it gives me.我完成了所有功能,但是当我尝试执行ls -lRa /homecatgcc我在执行一段时间后出现分段错误...我尝试使用 valgrind 搜索错误,但我不明白它给出的错误我。

At school someone told me that I have to align my pointers on 16 bytes to execute ls , etc. So I modified the size of the blocks that I allocate with sbrk to only get sizes multiple of 16 and my structure for holding the blocks malloced is 32 bytes.在学校有人告诉我,我必须将我的指针对齐 16 个字节才能执行ls等。所以我修改了我用sbrk分配的块的大小,只得到 16 的倍数,我的结构是用来保存 malloced 块的32 字节。 I verified with small hand made programs and all the pointers returned by my malloc are aligned on 16 bytes with this method.我用手工制作的小程序进行了验证,我的malloc返回的所有指针都使用此方法在 16 个字节上对齐。 Maybe there is a better way to align my pointers?也许有更好的方法来对齐我的指针?

Here is the error:这是错误:

/home/abinder/.cache/mozilla/firefox/wv0yeusd.default/cache2/doomed:
total 8
drwxr-xr-x. 2 abinder abinder 4096 11 févr. 17:08 .
drwx------. 4 abinder abinder 4096 11 févr. 17:06 ..

/home/abinder/.cache/mozilla/firefox/wv0yeusd.default/cache2/entries:
==3813== Invalid read of size 1
==3813==    at 0x550AF0D: strcoll_l (in /usr/lib64/libc-2.25.so)
==3813==    by 0x1171EB: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x1172C0: ??? (in /usr/bin/ls)
==3813==    by 0x1172C0: ??? (in /usr/bin/ls)
==3813==    by 0x1172AF: ??? (in /usr/bin/ls)
==3813==    by 0x1172AF: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x10DB5B: ??? (in /usr/bin/ls)
==3813==    by 0x1122CA: ??? (in /usr/bin/ls)
==3813==    by 0x10C53C: ??? (in /usr/bin/ls)
==3813==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==3813==
==3813==
==3813== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==3813==  Access not within mapped region at address 0x0
==3813==    at 0x550AF0D: strcoll_l (in /usr/lib64/libc-2.25.so)
==3813==    by 0x1171EB: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x1172C0: ??? (in /usr/bin/ls)
==3813==    by 0x1172C0: ??? (in /usr/bin/ls)
==3813==    by 0x1172AF: ??? (in /usr/bin/ls)
==3813==    by 0x1172AF: ??? (in /usr/bin/ls)
==3813==    by 0x1171B0: ??? (in /usr/bin/ls)
==3813==    by 0x10DB5B: ??? (in /usr/bin/ls)
==3813==    by 0x1122CA: ??? (in /usr/bin/ls)
==3813==    by 0x10C53C: ??? (in /usr/bin/ls)
==3813==  If you believe this happened as a result of a stack
==3813==  overflow in your program's main thread (unlikely but
==3813==  possible), you can try to increase the size of the
==3813==  main thread stack using the --main-stacksize= flag.
==3813==  The main thread stack size used in this run was 8388608.
==3813==
==3813== Process terminating with default action of signal 11 (SIGSEGV)
==3813==  General Protection Fault
==3813==    at 0x55C016C: _dl_catch_error (in /usr/lib64/libc-2.25.so)
==3813==    by 0x55BF8E6: __libc_dlclose (in /usr/lib64/libc-2.25.so)
==3813==    by 0x55EB5E4: free_mem (in /usr/lib64/libc-2.25.so)
==3813==    by 0x55EB1E1: __libc_freeres (in /usr/lib64/libc-2.25.so)
==3813==    by 0x4A296DB: _vgnU_freeres (vg_preloaded.c:77)
==3813==
==3813== HEAP SUMMARY:
==3813==     in use at exit: 1,313,866 bytes in 5,125 blocks
==3813==   total heap usage: 5,125 allocs, 0 frees, 1,313,866 bytes allocated
==3813==
==3813== LEAK SUMMARY:
==3813==    definitely lost: 1,307,936 bytes in 5,110 blocks
==3813==    indirectly lost: 0 bytes in 0 blocks
==3813==      possibly lost: 2,560 bytes in 10 blocks
==3813==    still reachable: 3,370 bytes in 5 blocks
==3813==         suppressed: 0 bytes in 0 blocks
==3813== Rerun with --leak-check=full to see details of leaked memory
==3813==
==3813== For counts of detected and suppressed errors, rerun with: -v
==3813== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

If you want to test my code:如果你想测试我的代码:

here is my struct for the linked list:这是我的链表struct

typedef struct s_memory {
    size_t             size;
    unsigned short int free;
    struct s_memory    *next;
    void               *data;
} memory_t;

here are my malloc , free and realloc functions:这是我的mallocfreerealloc函数:

#define align4(x)  (((((x) - 1) >> 4) << 4) + 16)

memory_t *list = NULL;

void show_alloc_mem(void) {
    show_list(list);
    fprintf(stdout, "\n");
}

void free(void *ptr) {
    unsigned char *ptr_casted = (unsigned char *)ptr;
    memory_t *to_free = ptr - sizeof(memory_t);
    memory_t *buff = list;

    if (ptr == NULL || ptr >= sbrk(0) || to_free->data != ptr)
        return;
    to_free->free = 1;
    if (buff != NULL && buff->free == 1) {
        while (buff != NULL && buff->free != 0) {
            list = list->next;
            brk(buff);
            buff = list;
        }
    } else
        *(ptr_casted) = (unsigned char)0;
}

void *malloc(size_t size) {
    memory_t *freed;
    void *newMem;

    size = align4(size);
    freed = search_freed(&list, size);
    if (freed == NULL) {
        newMem = add_in_memorylist(&list, size);
        if (newMem == NULL) {
            fprintf(stderr, "no more ram to alloc %ld !\n", size);
            return NULL;
        } else {
            return newMem;
        }
    } else
        resize_in_memory(freed, size);

    return ((void *)(unsigned char *)freed + sizeof(memory_t));
}

void *cpy_mem(memory_t *to_realloc, size_t size) {
    long double *new;
    long double *to_real_cast = (long double *)to_realloc;

    if (((void *)(unsigned char *)to_realloc +
            sizeof(memory_t) + to_realloc->size) == sbrk(0)) {
        new = sbrk(align4(size - to_realloc->size));
        if (new == (void *)-1)
            return NULL;
        to_realloc->size += align4(size - to_realloc->size);
        return ((void *)(unsigned char *)to_realloc + sizeof(memory_t));
    }
    new = malloc(align4(size));
    if (new == NULL)
        return NULL;
    for (size_t i = 0; i < to_realloc->size / 16 && i < size / 16; i++) {
        new[i] = to_real_cast[(sizeof(memory_t) / 16) + i];
    }
    free((void *)(unsigned char *)to_realloc + sizeof(memory_t));
    return new;
}

void *realloc(void *ptr, size_t size) {
    memory_t *to_realloc = ptr - sizeof(memory_t);

    if (ptr == NULL && size > 0)
        return malloc(align4(size));
    else if (size <= 0) {
        free(ptr);
        return NULL;
    } else
        return cpy_mem(to_realloc, size);
}

and here are the functions to handle the linked list:以下是处理链表的函数:

void resize_in_memory(memory_t *freed, size_t size) {
    memory_t *new_struct;
    unsigned char *new_struct_cast;

    freed->free = 0;
    if (freed->size >= size + sizeof(memory_t) + 16) {
        new_struct = ((void *)(unsigned char *)freed + sizeof(memory_t) + size);
        new_struct_cast = (unsigned char *)new_struct;
        new_struct->data = new_struct_cast + sizeof(memory_t);
        new_struct->size = freed->size - sizeof(memory_t) - size;
        new_struct->free = 1;
        new_struct->next = freed->next;
        freed->next = new_struct;
        freed->size = size;
    }
}

void *add_in_memorylist(memory_t **list, size_t size) {
    memory_t *new_struct = NULL;
    void *data_space = NULL;

    new_struct = sbrk(sizeof(memory_t));
    data_space = sbrk(size);
    if (new_struct == (void *)-1 || data_space == (void *)-1)
        return NULL;
    new_struct->data = data_space;
    new_struct->size = sbrk(0) - data_space;
    new_struct->free = 0;
    new_struct->next = *list;
    *list = new_struct;
    return data_space;
}

memory_t *merge_memory(memory_t *buff) {
    size_t size = 0;
    int ok = 0;
    memory_t *ptr = buff;

    while (ok == 0) {
        if (ptr->next == NULL || ptr->next->free == 0) {
            size += ptr->size;
            ok = 1;
        } else
            size += ptr->size + sizeof(memory_t);

        if (ptr->next != NULL)
            ptr = ptr->next;
    }
    if (ptr != buff)
        ptr->size = size;
    return ptr;
}

memory_t *search_freed(memory_t **list, size_t size) {
    memory_t *buff = *list;
    memory_t *ret = NULL;

    while (buff != NULL && ret == NULL) {
        if (buff->free == 0 && buff->next != NULL && buff->next->free == 1)
            buff->next = merge_memory(buff->next);
        if (buff->size >= size && buff->free == 1)
            ret = buff;
        buff = buff->next;
    }
    return ret;
}

PS: I am not asking you to give me a working code from what I gave you but to tell me what I did wrong and eventually where in my code I made mistakes. PS:我不是要你根据我给你的代码给我一个工作代码,而是告诉我我做错了什么,最终我在代码中哪里出错了。

Here are some remarks:以下是一些注意事项:

The macro to round the size up to a multiple of 16 is usually written without shifts:将大小四舍五入为 16 的倍数的宏通常无需移位即可编写:

    #define align4(x)  (((x) + 15) & ~(size_t)15)

Bear in mind that both versions convert extremely large sizes to 0 , which may lead to successful allocations with an incorrect size.请记住,这两个版本都将极大的大小转换为0 ,这可能会导致大小不正确的成功分配。

Regarding the linked list structure:关于链表结构:

  • the member data seems redundant since it always points to the byte that follows the structure.成员data似乎是多余的,因为它总是指向结构后面的字节。 You could instead use this space to make the list doubly linked to simplify free block coalescing in free and remove the need for merge_memory .你也可以使用这个空间,使双链接,以简化空闲块凝聚在列表中free和删除的需要merge_memory

In function free() :在函数free()

  • missing cast: memory_t *to_free = ptr - sizeof(memory_t);缺少演员表: memory_t *to_free = ptr - sizeof(memory_t);

  • calling brk(buff);呼叫brk(buff); in free() seems incorrect.free()似乎不正确。 You release memory back to the system that might not be the last free block.您将可能不是最后一个空闲块的内存释放回系统。

  • what is the purpose of *(ptr_casted) = (unsigned char)0; *(ptr_casted) = (unsigned char)0;的目的是什么*(ptr_casted) = (unsigned char)0; ? ?

In function malloc() :在函数malloc()

  • ((void *)(unsigned char *)freed + sizeof(memory_t)); is incorrect because the parentheses are misplaced: you add the size to a void * pointer.不正确,因为括号放错了位置:将大小添加到void *指针。 The expression could be simplified as (void *)(freed + 1);表达式可以简化为(void *)(freed + 1); or simply freed + 1 .或者干脆freed + 1

in function realloc() :在函数realloc()

  • void * arithmetic again: memory_t *to_realloc = ptr - sizeof(memory_t); void *再次算术: memory_t *to_realloc = ptr - sizeof(memory_t); Use this instead: memory_t *to_realloc = (memory_t *)ptr - 1;改用这个: memory_t *to_realloc = (memory_t *)ptr - 1;

  • because of the overflow problem, you should not write return malloc(align4(size));因为溢出问题,你不应该写return malloc(align4(size)); but simply return malloc(size);但只需return malloc(size);

In function add_in_memorylist :在函数add_in_memorylist

  • you request 2 different blocks for the linked list srtucture and the data block.您为链表结构和数据块请求 2 个不同的块。 This leads to an important overhead and is inconsistent with the method used in free to locate the list link.这会导致一个重要的开销,并且与free用于定位列表链接的方法不一致。 You should instead request a block of size size + sizeof(memory_t) , rounded up to a multiple of the page size, a multiple of 4K for this matter.相反,您应该请求一个大小为size + sizeof(memory_t) ,四舍五入为页面大小的倍数,为此是 4K 的倍数。

  • similarly, you keep calling sbrk(0) .同样,您不断调用sbrk(0) You should instead use a global variable to keep track of the arena size and only make system calls to extend it (or possibly shrink it, but that's more difficult).您应该改为使用全局变量来跟踪 arena 大小,并且只进行系统调用来扩展它(或者可能缩小它,但这更困难)。

Also note that you should redefine calloc() to ensure that the version from the C library does not get linked as this version might be incompatible with your redefined version of malloc() .另请注意,您应该重新定义calloc()以确保不会链接来自 C 库的版本,因为此版本可能与您重新定义的malloc()版本不兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM