对齐的内存管理? [英] Aligned memory management?

查看:125
本文介绍了对齐的内存管理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有关于管理对齐的内存块的几个相关问题。跨平台的答案将是理想的。然而,正如我pretty的确定一个跨平台的解决方案是不存在的,我感兴趣的主要是Windows和Linux,并以一(多)较小程度上的Mac OS和FreeBSD。

  1. 什么是得到一个内存块16字节边界对齐的最好方法? (我知道使用的malloc(),分配一些额外的空间,然后碰撞指针到一个正确对齐的价值。我希望为琐碎的方法东西少一些杂牌-Y,但。此外,请参阅下面的其他问题。)

  2. 如果我用普通的老式的malloc(),分配额外的空间,然后移动鼠标指针高达哪里会被正确对齐,是有必要保持的指针块的开始围绕用于释放? (呼叫免费()的指针指向块的中间似乎在Windows实践工作,但我不知道什么标准说和,即使标准说你不能,无论是它的工作原理在实践中的所有主要操作系统的。我不关心晦涩 DS9K 般的操作系统的。)

  3. 这是硬/有趣的部分。什么是重新分配,而preserving对准一个内存块的最佳方法是什么?理想情况下,这将是一些更聪明的不是调用的malloc(),复制,然后调用免费()旧块。我想做到这一点的地方,可能的。

解决方案
  1. 如果您的实现有一个需要16字节对齐的标准数据类型(很长很长为例),的malloc 已确保了您退回块将被正确对齐。 C99状态的部分7.20.3 返回的指针,如果分配成功对齐适当,以便它可以被分配给一个指向任何类型的对象。

  2. 您的有无以的回传完全相同的地址到免费你被给出的malloc 。没有例外。所以,是的,你需要保持原有的副本。

  3. 请参阅上述(1)如果你已经有了一个16字节对齐要求的类型。

除此之外,你可能会发现,你的的malloc 的实施给你16字节对齐地址反正效率,尽管它不是由标准的保证。如果你需要它,你总是可以实现你的的分配器。

我自己,我会实施 malloc16 层上的malloc ,将使用以下结构的顶部:

 一些填充对齐(0-15个字节)
填充的大小(1字节)
16字节对准区域
 

然后让你的 malloc16()函数调用的malloc 来获得一个块比要求的更大的16个字节,计算出其中对准面积应,把填充长度正好之前和返回对准区域的地址。

有关 free16 ,您只需看字节给得到填充长度的地址之前,从制定出malloc分配块的实际地址,并传递给免费

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

  void *的malloc16(为size_t S){
    无符号字符* P;
    无符号字符* porig =的malloc(S + 0×10); //分配额外
    如果(porig == NULL)返回NULL; //赶出来的记忆
    p值=(porig + 16)及(〜0xF的); //插入填充
    *(P-1)= P  -  porig; //店的空白大小
    返回磷;
}

无效free16(无效* P){
    无符号字符* porig = P; //工作了原有的
    porig = porig  -  *(porig-1); //减去填充
    免费(porig); //那么自由了
}
 

malloc16 P =(porig + 16)及魔术线; (〜0xF的); 这增加16到地址则设置低4位为0时,在效果把它回到下一个最低的对准点( 16 保证它是过去的maloc'ed块的实际开始)。

现在,我不主张在code以上是什么的的kludgey。你将不得不在感兴趣的平台进行测试,看它是否是可行的。它的主要优点是,它抽象掉了丑陋位,所以你永远不必担心。

I have a few related questions about managing aligned memory blocks. Cross-platform answers would be ideal. However, as I'm pretty sure a cross-platform solution does not exist, I'm mainly interested in Windows and Linux and to a (much) lesser extent Mac OS and FreeBSD.

  1. What's the best way of getting a chunk of memory aligned on 16-byte boundaries? (I'm aware of the trivial method of using malloc(), allocating a little extra space and then bumping the pointer up to a properly aligned value. I'm hoping for something a little less kludge-y, though. Also, see below for additional issues.)

  2. If I use plain old malloc(), allocate extra space, and then move the pointer up to where it would be correctly aligned, is it necessary to keep the pointer to the beginning of the block around for freeing? (Calling free() on pointers to the middle of the block seems to work in practice on Windows, but I'm wondering what the standard says and, even if the standard says you can't, whether it works in practice on all major OS's. I don't care about obscure DS9K-like OS's.)

  3. This is the hard/interesting part. What's the best way to reallocate a memory block while preserving alignment? Ideally this would be something more intelligent than calling malloc(), copying, and then calling free() on the old block. I'd like to do it in place where possible.

解决方案

  1. If your implementation has a standard data type that needs 16-byte alignment (long long for example), malloc already guarantees that your returned blocks will be aligned correctly. Section 7.20.3 of C99 states The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object.

  2. You have to pass back the exact same address into free as you were given by malloc. No exceptions. So yes, you need to keep the original copy.

  3. See (1) above if you already have a 16-byte-alignment-required type.

Beyond that, you may well find that your malloc implementation gives you 16-byte-aligned addresses anyway for efficiency although it's not guaranteed by the standard. If you require it, you can always implement your own allocator.

Myself, I'd implement a malloc16 layer on top of malloc that would use the following structure:

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

Then have your malloc16() function call malloc to get a block 16 bytes larger than requested, figure out where the aligned area should be, put the padding length just before that and return the address of the aligned area.

For free16, you would simply look at the byte before the address given to get the padding length, work out the actual address of the malloc'ed block from that, and pass that to free.

This is untested but should be a good start:

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
}

The magic line in the malloc16 is p = (porig + 16) & (~0xf); which adds 16 to the address then sets the lower 4 bits to 0, in effect bringing it back to the next lowest alignment point (the +16 guarantees it is past the actual start of the maloc'ed block).

Now, I don't claim that the code above is anything but kludgey. You would have to test it in the platforms of interest to see if it's workable. Its main advantage is that it abstracts away the ugly bit so that you never have to worry about it.

这篇关于对齐的内存管理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆