在 void* 中使用指针算术

问题描述

我的机器是 ubuntu 20.04

我有一个作业说 “使用系统调用(mmap 和 munmap)实现您自己的动态内存分配函数:mymalloc 和 myfree,它们具有与 malloc 相同的功能并且从标准 C 库中释放。将实现保存在文件 mymalloc.h 和 mymalloc.c 中.”

然后它说 “我们必须至少分配所需的长度 + 用于存储的变量的大小 长度 (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);

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

并且它给出警告“在算术[-Wpointer arith]中使用的指针类型'void *'”

ı 必须将长度存储在第一个元素中,因为赋值说明了这一点,但我不警告我想编写干净的代码。它有法律依据。我已经读过Pointer arithmetic when void has unknown size 但找不到任何答案来解决它。

解决方法

当您使用指针算术 (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 bitsnext 16 bits或{{1} }}?)。你不应该使用 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); // 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。)

,

正如您所发现的,除非您使用 GCC 扩展或类似扩展,否则您无法使用 void* 进行算术运算。

简单的解决方案是:不要使用 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 函数中分配的同一个内存对象。

注意:

如果您要创建一个不仅用于教育目的的函数,您还需要处理返回给调用者的地址的正确对齐。

,

处理 void* 时,对 char*unsigned char* 指针进行算术运算。

void *allocated_mem_pointer = (char*)data + sizeof(size_t);

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...