c - 对齐内存管理?

标签 c memory-management malloc alignment realloc

我有几个关于管理对齐内存块的相关问题。跨平台的答案将是理想的。但是,由于我非常确定不存在跨平台解决方案,因此我主要对 Windows 和 Linux 感兴趣,对 Mac OS 和 FreeBSD 的(程度)较小。

  1. 让一 block 内存在 16 字节边界上对齐的最佳方法是什么? (我知道使用 malloc() 的简单方法,分配一点额外的空间,然后将指针向上移动到正确对齐的值。我希望能少一些困惑-不过,是的。另外,请参阅下面的其他问题。)

  2. 如果我使用普通的旧 malloc(),分配额外的空间,然后将指针向上移动到正确对齐的位置,是否有必要将指针保持在开头释放周围的 block ? (在指向 block 中间的指针上调用 free() 似乎在 Windows 上实际上有效,但我想知道标准是怎么说的,即使标准说你不能,是否它实际上适用于所有主要操作系统。我不关心晦涩难懂的 DS9K -就像操作系统一样。)

  3. 这是困难/有趣的部分。在保持对齐的同时重新分配内存块的最佳方法是什么?理想情况下,这比调用 malloc()、复制然后在旧 block 上调用 free() 更智能。我想尽可能就地进行。

最佳答案

  1. 如果您的实现具有需要 16 字节对齐的标准数据类型(例如 long long),malloc 已经保证您返回的 block 将是正确对齐。 C99 的第 7.20.3 节指出 如果分配成功则返回的指针适当对齐,以便它可以分配给指向任何类型对象的指针。

  2. 必须将与malloc 给您的地址完全相同的地址传回free。没有异常(exception)。所以是的,您需要保留原件。

  3. 如果您已经有 16 字节对齐要求的类型,请参阅上面的 (1)。

除此之外,您可能会发现您的 malloc 实现无论如何都会为您提供 16 字节对齐的地址以提高效率,尽管标准并不能保证这一点。如果需要,您始终可以实现您的自己的分配器。

我自己,我将在 malloc 之上实现一个 malloc16 层,该层将使用以下结构:

some padding for alignment (0-15 bytes)
size of padding (1 byte)
16-byte-aligned area

然后让你的 malloc16() 函数调用 malloc 得到一个比请求大 16 字节的 block ,找出对齐区域应该在哪里,把填充长度放在刚刚好在此之前返回对齐区域的地址。

对于 free16,您只需查看给定地址之前的字节以获得填充长度,从中计算出 malloc block 的实际地址,并将其传递给 免费

这是未经测试的,但应该是一个好的开始:

void *malloc16 (size_t s) {
    unsigned char *p;
    unsigned char *porig = malloc (s + 0x10);   // allocate extra
    if (porig == NULL) return NULL;             // catch out of memory
    p = (porig + 16) & (~0xf);                  // insert padding
    *(p-1) = p - porig;                         // store padding size
    return p;
}

void free16(void *p) {
    unsigned char *porig = p;                   // work out original
    porig = porig - *(porig-1);                 // by subtracting padding
    free (porig);                               // then free that
}

malloc16 中的魔法行是 p = (porig + 16) & (~0xf); 它将地址加 16 然后将低 4 位设置为0,实际上将它带回到下一个最低对齐点(+16 保证它已经过了 maloc block 的实际开始)。

现在,我并不是说上面的代码是什么而是杂七杂八的东西。您必须在感兴趣的平台上对其进行测试,看看它是否可行。它的主要优点是它抽象掉了丑陋的部分,因此您永远不必担心它。

关于c - 对齐内存管理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5061392/

相关文章:

c - gdb 调试函数不在调用堆栈中

c - 在 Raspberry 中使用 C 语言的时钟

objective-c - 在内存中保存一个 c 数组,以便以后可以使用指针访问它

c++ - 我怎么知道数组中元素的数量

c++ - 在死锁 futex 中调用 malloc 和程序时出现段错误

c - CPU 与使用 malloc 的 Wall time 测量值的奇怪差异

c - 如何让 callgrind 转储源代码行信息?

objective-c - 在 ViewController 之间传递 NSArray。是通过指针还是通过复制?

c - mmap 分配多个页面

c - 了解指针(在 C 中): converting int pointer to char and changing values