[英]malloc align memory C
我必须为学校项目重新编码malloc
、 free
和realloc
。
我完成了所有功能,但是当我尝试执行ls -lRa /home
或cat
或gcc
我在执行一段时间后出现分段错误...我尝试使用 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;
这是我的malloc
、 free
和realloc
函数:
#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.