【发布时间】:2021-12-03 02:12:51
【问题描述】:
我正在尝试在 C 中从头开始实现 malloc,但是遇到了分段错误。当我通过 Valgrind 输入代码时,它说
First node at: 0x422c000
Size of free chunk: 8032
Next node at: 0x3e700000028
==350== Invalid read of size 4
==350== at 0x1087A6: printFreeList (class_demo.c:29)
==350== by 0x108840: test1 (class_demo.c:45)
==350== by 0x108732: main (class_demo.c:16)
==350== Address 0x3e700000030 is not stack'd, malloc'd or (recently) free'd
这是相关功能,如果需要我可以提供更多信息。该函数的一般工作方式是使用单链表来跟踪可用空间。每当我分配空间时,我都会为分配的块设置一个标头,指示块大小和一个幻数,然后返回分配空间的地址。
// allocate size bytes of memory
void *my_malloc(uint32_t size){
// error if size is negative
// if (size < 0) {
// my_errno = MYENOMEM;
// return NULL;
// }
// make sure using 8 byte aligned size
size = actual_size(size);
// calculate minimum chunk size
int minimum_chunk_size = minimum_chonk_size(size);
// if no freelistnode create one
if (free_list_begin() == NULL) {
head = (FreeListNode)sbrk(8192);
head->flink = NULL;
head->size = 8192;
}
// initialize variables
head = free_list_begin();
struct freelistnode * prev = NULL;
struct freelistnode * current = head;
void* ptr;
// find where to allocate chunk
while (current != NULL) {
// large enough
if (current->size >= minimum_chunk_size) {
// set return address
ptr = current;
if (current->size - minimum_chunk_size >= 16) { // allocate tail end
// set up new freelistnode
struct freelistnode * new = (FreeListNode)(ptr + minimum_chunk_size);
new->size = current->size - minimum_chunk_size;
if (prev != NULL) {
prev->flink = new;
}
new->flink = current->flink;
} else {
// remove current node
if (prev != NULL) {
prev->flink = current->flink;
} else {
head = current->flink;
}
}
break;
// need more space
} else if (current->flink == NULL) {
if (minimum_chunk_size <= 8192) {
// set return address
ptr = sbrk(8192);
if (8192 - minimum_chunk_size >= 16) { // allocate tail end
// set up new freelistnode
struct freelistnode * new = (FreeListNode)(ptr + minimum_chunk_size);
new->size = 8192 - minimum_chunk_size;
if (prev != NULL) {
prev->flink = new;
}
new->flink = current->flink;
}
} else {
// set return address
ptr = sbrk(minimum_chunk_size);
}
break;
// keep going through list
} else {
prev = current;
current = current->flink;
}
}
// set header
*((uint32_t*)ptr) = minimum_chunk_size;
*((int*)(ptr + 4)) = 999;
// return the address
return ptr + 8;
}
当我注释掉上面函数中的两行时:
// set header
*((uint32_t*)ptr) = minimum_chunk_size;
*((int*)(ptr + 4)) = 999;
分段错误消失了。但我看不出这两行是如何导致错误的。
这是调用函数的程序class_demo.c
#include "my_malloc.h"
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void test1();
int main(int argc, const char * argv[])
{
test1();
return 0;
}
void printFreeList(){
FreeListNode ptr = free_list_begin();
printf("First node at: %p\n", ptr);
printf("Size of free chunk: %d\n", ptr->size);
ptr=ptr->flink;
while(ptr != NULL){
printf("Next node at: %p\n", ptr);
printf("Size of free chunk: %d\n", ptr->size);
ptr = ptr->flink;
}
}
void test1(){
char *a = my_malloc(32);
printFreeList();
}
【问题讨论】:
-
if (size < 0) {应该给你一个警告..size是unsigned,所以它不可能是 -
好的,谢谢,有道理
-
不确定它是否相关,但你真的应该在每次调用它时检查
sbrk的返回值。这些调用中的任何一个都可能失败(返回(void *)-1。) -
@NateEldredge 好的,谢谢,我现在看看
-
您是否尝试按照我在回答中所说的去做?
标签: c segmentation-fault malloc valgrind