我的机器是ubuntu 20.04
我有一份作业说使用系统调用(mmap和munmap)实现您自己的动态内存分配函数:mymalloc和myfree,它们具有与标准C库中的malloc和free相同的功能。将实现保存在mymalloc.h和mymalloc .">
文件中然后它说我们必须至少分配所需的长度+用于存储的变量的大小长度(size_t)。我们将长度存储为第一个元素,然后返回下一个元素。">
这是我的代码(size是size_t类型的参数)
size_t total_size = size + sizeof(size_t);
size_t allocation_overflow = total_size % page_size;
if(allocation_overflow > 0)
total_size += page_size - allocation_overflow;
void *data = mmap(NULL ,total_size, PROT_EXEC | PROT_READ | PROT_WRITE , MAP_PRIVATE , 0 , 0);
// size_ptr will point to stored size
size_t *size_ptr =(size_t *)data;
size_ptr[0] = total_size;
// pointer to allocated memory
void* allocated_mem_pointer = data + sizeof(size_t);
并给出警告"指针类型'void*'用于算术[-Wpointer arith]">
必须将长度存储在第一个元素中,因为赋值说明了这一点,但我不警告我想编写干净的代码。İS这是合法的。我已经读指针算术时,void有未知的大小但是我找不到解决它的答案。
正如你所发现的,你不能用void*
做算术,除非你使用GCC扩展或类似的。
简单的解决方案是:不要使用void*
。
在你的代码中已经有
// size_ptr will point to stored size
size_t *size_ptr =(size_t *)data;
size_ptr[0] = total_size;
现在要计算计数器头后面的地址。
arr[0]
后面的元素就是arr[1]
。
使用此命令获取来电者的地址:
// pointer to allocated memory
void* allocated_mem_pointer = &size_ptr[1];
当你想回到你的myfree
函数头,你可以做类似的技巧:
void myfree(void*addr) {
size_t *buff = (size_t*) addr;
size_t header = buff[-1];
// ...
}
这是有效的,因为buff[-1]
指向最初在myalloc
函数中分配的相同内存对象。
注意:
如果您要创建的函数不仅用于教育目的,您还需要处理返回给调用者的地址的正确对齐。
当您使用指针算术(ie add a number to pointer
)时,您需要正确键入指针:
IntPointer32Bits + 1 => will give the address of the next adjacent 32 bits integer
IntPointer16Bits + 1 => will give the address of the next adjacent 16 bits integer
指针运算的结果地址取决于指针类型。
void* allocated_mem_pointer = data + sizeof(size_t);
在这种情况下,data
是void *
,所以指针运算对编译器来说不清楚(需要计算下一个8 bits
,next 16 bits
或next 32 bits
?)你不应该使用void *
,但你应该有一个真正的类型,我假设uint8_t
。
size_t total_size = size + sizeof(size_t);
size_t allocation_overflow = total_size % page_size;
if(allocation_overflow > 0)
total_size += page_size - allocation_overflow;
uint8_t *data = mmap(NULL ,total_size, PROT_EXEC | PROT_READ | PROT_WRITE , MAP_PRIVATE , 0 , 0);
// size_ptr will point to stored size
size_t *size_ptr =(size_t *)data;
size_ptr[0] = total_size;
// pointer to allocated memory
uint8_t *allocated_mem_pointer = data + sizeof(size_t);
在这种情况下,你的意图对编译器来说是非常清楚的:allocated_mem_pointer
是由uint8_t
组成的内存区域,计算出的地址是data
的基址,偏移量为size_t
字节。(运算符sizeof
返回的字节数即uint8_t
)
处理void*
时,对char*
或unsigned char*
指针进行算术处理。
void *allocated_mem_pointer = (char*)data + sizeof(size_t);