【问题标题】:What is the difference between &address + sizeof(type) and &address + 1?&address + sizeof(type) 和 &address + 1 有什么区别?
【发布时间】:2018-12-14 16:52:59
【问题描述】:

我正在尝试重新编码 malloc 函数。
假设我们有一个这样的结构:

typedef struct      s_block
{
    char            is_free;
    size_t          size;
    struct s_block  *next;
    void            *memory;
}                   t_block;

我用 mmap 分配一页内存,然后将它转换成一个大的 t_block。
然后,我有 1 个大小为 4064 的块(4096 - t_block 的大小)。
例如,如果我调用我的 malloc 大小为 12,这就是我所做的:

block->next = &block + 1 + size // Setting the next block
block->next->size = block->size - size - sizeof(t_block); // 4064 - 12 - 32
block->size = size; // 12
block->is_free = NOT_FREED;
block->memory = &block + 1;
block->next->memory = &(block->next) + 1;
block->next->next = NULL;
block->next->is_free = FREE;

我在使用 + 1 或 + sizeof(t_block) 时经常遇到问题。 那么,有什么区别:

block->next = &block + 1 + size;

和:

block->next = &block + sizeof(t_block) + size;

?

【问题讨论】:

  • 这些陈述看起来都不正确。应该是block->next = &block + sizeof(s_block),假设块是连续的。
  • &block + sizeof(block) 将产生一个指向block 地址加上sizeof(block)*sizeof(block) 字节的指针。
  • 但是很有可能这些块是连续的,除非你将它们存储在一个数组中,这有点违背链表的目的。
  • @RobertHarvey 我不认为这些块是连续的 - 分配的内存看起来它可能位于 个块之间。这是错误的,因为它错误地假设 struct s_block 没有对齐限制。
  • 实际上块应该是连续的:|t_block metadata|___memory_asked___|t_block metadata|___memory_asked___|等等...下一个块的第一个块链接到下一个块,即位置&块+块元数据的大小+请求内存的大小。当我将它们放置在使用 mmap() 获得的内存页面中时,这些块应该是连续的

标签: c unix memory-management malloc mmap


【解决方案1】:

假设block 被声明为t_block *,并且您希望在此块和下一个块之间使用size 字节,那么您所期望的也不是。由于&block 是指针的地址,因此对其进行的任何指针运算都基于指针的大小,而不是结构的大小。

你真正想要的是:

block->next = (t_block *)((char *)block + sizeof(t_block) + size);

通过首先将block 转换为char *,对其执行的任何指针运算都适用于单个字节,而不是结构大小的倍数。所以我们从块的地址开始,向上移动sizeof(t_block)字节到用户内存的开头,然后size更多字节到该内存的末尾和下一个块的开头。

此外,由于结构的对齐要求,您需要确保下一个块正确对齐。你可以这样做:

size_t block_align = (sizeof(t_block) - (size % sizeof(t_block))) % sizeof(t_block);
block->next = (t_block *)((char *)block + sizeof(t_block) + block_align + size);

【讨论】:

  • 创建块->下一步工作,谢谢!但是对于对齐,这样的事情会不会更容易? :size += sizeof(t_block); while (size % 16) size++;
  • @Elynad 假设 sizeof(t_block) 是 16,那么这也可以。
  • 不,sizeof(t_block) 是 32,但不是基于处理器对齐?我把 16 作为我的处理器每个“转”读取 16 个字节
【解决方案2】:

((Type*)(p)) + n == ((char*)(p)) + sizeof(Type)*n

类型指针上的算术(即实际上只是加/减)按指向类型的大小(sizeof(char) 定义为 1)进行缩放。

【讨论】:

    猜你喜欢
    • 2021-12-26
    • 2017-08-24
    • 1970-01-01
    • 2015-04-15
    • 2014-08-13
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多