gpt4 book ai didi

C++ - 对齐内存

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:35:10 25 4
gpt4 key购买 nike

我很想了解这两条线上发生了什么

const int PAGES = 8 * 1024;

// PAGES + extra 4KiB for alignment
uint8_t * mem = new uint8_t [ PAGES * CCPU::PAGE_SIZE + CCPU::PAGE_SIZE ];

// align to a mutiple of 4KiB
uint8_t * memAligned = (uint8_t *) (( ((uintptr_t) mem) + CCPU::PAGE_SIZE - 1) & ~(uintptr_t) ~CCPU::ADDR_MASK );

特别是最后一行,我什么都不懂...

最佳答案

它分配指向页面对齐内存块的指针,即 PAGES 页数,使用 C++ 分配器而不是更多操作系统特定的专用对齐分配函数(例如 POSIX's posix_memalign or C11's aligned_alloc)。

首先,它分配 PAGES + 1 个内存页(可能是页对齐的,也可能不是页对齐的),然后它向前调整结果指针,使其指向结果中第一个页对齐的字节。通过过度分配一个额外的页面,它知道它肯定会有足够大的分配以拥有超过该点的 PAGES 个可用页面。程序只需要确保它在完成时deletemem,而不是memAligned(删除后者可能会导致程序崩溃,后来由于堆损坏,或者只是内存泄漏;这是未定义的行为,因此将您的计算机熔化成渣是合法的行为)。

最后一行在数值上等同于四舍五入到页面大小的下一个倍数;它将 PAGE_SIZE - 1 添加到指针(所以如果指针已经页对齐,它仍然在同一页中,否则它被移动到下一页),然后屏蔽掉地址的低位(在“页面已对齐”的情况下撤消添加,在所有其他情况下,将指针重置为指向 mem 中未对齐指针之后的第一页的开头)。

详细信息:~ 是按位取反,所以 ADDR_MASK 对于 4096 字节的页面可能类似于 0x00000FFF,变为 0xFFFFF000(翻转所有位)。当 &-ing 一个值时,只保留两个操作数中设置的位。举个例子:对于一个 32 位指针,我们假设 new 给了我们 0xDEADBEEF,并且 PAGE_SIZE 是 4096。加上 4095 (0xFFF) 意味着我们有'0xDEADCEEE'。然后,我们使用 0xFFFFF000 进行屏蔽,这会消除低位,从而为我们提供 0xDEADC000,即 0xDEADBEEF 之后的第一个页面对齐地址。 new 返回的任何非页面对齐地址都会发生同样的事情。

如果该值已经页对齐,例如 0xDEADB000,添加 4095/0xFFF 得到我们 0xDEADBFFF(注意没有位在 0xDEADB 中更改),因此当我们屏蔽以获取对齐地址时,我们再次返回 0xDEADB000,因为我们已经进行了页面对齐。

转换为 uintptr_t 是为了确保我们可以使用数学运算符操作地址,并确保按位反转填充匹配指针所需的所有位(如果大小不合适,您可能反转,然后上转换,突然间你的左边会有一堆零,而不仅仅是右边,你最终会屏蔽掉指针中的重要位,所以它指向了一个完全不同和错误的地方)。

关于C++ - 对齐内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36630960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com