繁体   English   中英

malloc 对齐内存 C

[英]malloc align memory C

我必须为学校项目重新编码mallocfreerealloc

我完成了所有功能,但是当我尝试执行ls -lRa /homecatgcc我在执行一段时间后出现分段错误...我尝试使用 valgrind 搜索错误,但我不明白它给出的错误我。

在学校有人告诉我,我必须将我的指针对齐 16 个字节才能执行ls等。所以我修改了我用sbrk分配的块的大小,只得到 16 的倍数,我的结构是用来保存 malloced 块的32 字节。 我用手工制作的小程序进行了验证,我的malloc返回的所有指针都使用此方法在 16 个字节上对齐。 也许有更好的方法来对齐我的指针?

这是错误:

/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)

如果你想测试我的代码:

这是我的链表struct

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

这是我的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);
}

以下是处理链表的函数:

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:我不是要你根据我给你的代码给我一个工作代码,而是告诉我我做错了什么,最终我在代码中哪里出错了。

以下是一些注意事项:

将大小四舍五入为 16 的倍数的宏通常无需移位即可编写:

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

请记住,这两个版本都将极大的大小转换为0 ,这可能会导致大小不正确的成功分配。

关于链表结构:

  • 成员data似乎是多余的,因为它总是指向结构后面的字节。 你也可以使用这个空间,使双链接,以简化空闲块凝聚在列表中free和删除的需要merge_memory

在函数free()

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

  • 呼叫brk(buff); free()似乎不正确。 您将可能不是最后一个空闲块的内存释放回系统。

  • *(ptr_casted) = (unsigned char)0;的目的是什么*(ptr_casted) = (unsigned char)0; ?

在函数malloc()

  • ((void *)(unsigned char *)freed + sizeof(memory_t)); 不正确,因为括号放错了位置:将大小添加到void *指针。 表达式可以简化为(void *)(freed + 1); 或者干脆freed + 1

在函数realloc()

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

  • 因为溢出问题,你不应该写return malloc(align4(size)); 但只需return malloc(size);

在函数add_in_memorylist

  • 您为链表结构和数据块请求 2 个不同的块。 这会导致一个重要的开销,并且与free用于定位列表链接的方法不一致。 相反,您应该请求一个大小为size + sizeof(memory_t) ,四舍五入为页面大小的倍数,为此是 4K 的倍数。

  • 同样,您不断调用sbrk(0) 您应该改为使用全局变量来跟踪 arena 大小,并且只进行系统调用来扩展它(或者可能缩小它,但这更困难)。

另请注意,您应该重新定义calloc()以确保不会链接来自 C 库的版本,因为此版本可能与您重新定义的malloc()版本不兼容。

暂无
暂无

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

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