簡體   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