_aligned_malloc自己实现

  1. void* aligned_malloc(size_t size, size_t align)  
  2. {  
  3.     void* raw_malloc_ptr;       //初始分配的地址  
  4.     void* aligned_ptr;          //最终我们获得的alignment地址  
  5.       
  6.     if( align & (align - 1) )   //如果alignment不是2的n次方,返回  
  7.     {  
  8.         errno = EINVAL;  
  9.         return ( (void*)0 );  
  10.     }  
  11.       
  12.     if( 0 == size )  
  13.     {  
  14.         return ( (void*)0 );  
  15.     }   
  16.       
  17.     //将alignment置为至少为2*sizeof(void*),一种优化做法。  
  18.     if( align < 2*sizeof(void*) )  
  19.     {  
  20.         align = 2 * sizeof(void*);  
  21.     }  
  22.       
  23.     raw_malloc_ptr = malloc(size + align);  
  24.     if( !raw_malloc_ptr )  
  25.     {  
  26.         return ( (void*)0 );  
  27.     }  
  28.       
  29.     //Align  We have at least sizeof (void *) space below malloc'd ptr.   
  30.     aligned_ptr = (void*) ( ((size_t)raw_malloc_ptr + align) & ~((size_t)align - 1));  
  31.       
  32.     ( (void**)aligned_ptr )[-1] = raw_malloc_ptr;  
  33.       
  34.     return aligned_ptr;  
  35. }  

  1. void* aligned_free(void * aligned_ptr)  
  2. {  
  3.     if( aligned_ptr )  
  4.     {  
  5.         free( ((void**)aligned_ptr)[-1] );  
  6.     }  
  7. }  


再给出一套对比一下,可能讲的更详细:


  1. void* aligned_malloc(size_t size, int alignment)    
  2.     {    
  3.         // 分配足够的内存, 这里的算法很经典, 早期的STL中使用的就是这个算法    
  4.     
  5.         // 首先是维护FreeBlock指针占用的内存大小    
  6.         const int pointerSize = sizeof (void*);    
  7.     
  8.         // alignment - 1 + pointerSize这个是FreeBlock内存对齐需要的内存大小    
  9.         // 前面的例子sizeof(T) = 20, __alignof(T) = 16,    
  10.         // g_MaxNumberOfObjectsInPool = 1000    
  11.         // 那么调用本函数就是alignedMalloc(1000 * 20, 16)    
  12.         // 那么alignment - 1 + pointSize = 19    
  13.         const int requestedSize = size + alignment - 1 + pointerSize;    
  14.     
  15.         // 分配的实际大小就是20000 + 19 = 20019    
  16.         void* raw = malloc(requestedSize);    
  17.     
  18.         // 这里实Pool真正为对象实例分配的内存地址    
  19.         uintptr_t start = (uintptr_t) raw + pointerSize;    
  20.         // 向上舍入操作    
  21.         // 解释一下, __ALIGN - 1指明的是实际内存对齐的粒度    
  22.         // 例如__ALIGN = 8时, 我们只需要7就可以实际表示8个数(0~7)    
  23.         // 那么~(__ALIGN - 1)就是进行舍入的粒度    
  24.         // 我们将(bytes) + __ALIGN-1)就是先进行进位, 然后截断    
  25.         // 这就保证了我是向上舍入的    
  26.         // 例如byte = 100, __ALIGN = 8的情况    
  27.         // ~(__ALIGN - 1) = (1 000)B    
  28.         // ((bytes) + __ALIGN-1) = (1 101 011)B    
  29.         // (((bytes) + __ALIGN-1) & ~(__ALIGN - 1)) = (1 101 000 )B = (104)D    
  30.         // 104 / 8 = 13, 这就实现了向上舍入    
  31.         // 对于byte刚好满足内存对齐的情况下, 结果保持byte大小不变    
  32.         // 记得《Hacker's Delight》上面有相关的计算    
  33.         // 这个表达式与下面给出的等价    
  34.         // ((((bytes) + _ALIGN - 1) * _ALIGN) / _ALIGN)    
  35.         // 但是SGI STL使用的方法效率非常高     
  36.         void* aligned = (void*) ((start + alignment - 1) & ~(alignment - 1));    
  37.     
  38.         // 这里维护一个指向malloc()真正分配的内存    
  39.         *(void**) ((uintptr_t) aligned - pointerSize) = raw;    
  40.     
  41.         // 返回实例对象真正的地址    
  42.         return aligned;    
  43.     }    
  44.   
  45.   
  46.     // 这里是内部维护的内存情况    
  47.     //                   这里满足内存对齐要求    
  48.     //                             |    
  49.     // ----------------------------------------------------------------------    
  50.     // | 内存对齐填充 | 维护的指针 | 对象1 | 对象2 | 对象3 | ...... | 对象n |    
  51.     // ----------------------------------------------------------------------    
  52.     // ^                     | 指向malloc()分配的地址起点    
  53.     // |                     |    
  54.     // -----------------------    
  55.     void aligned_free(void* aligned)    
  56.     {    
  57.         // 释放操作很简单了, 参见上图    
  58.         void* raw = *(void**) ((uintptr_t) aligned - sizeof (void*));    
  59.         free(raw);    
  60.     }    
  61.     
  62.     bool isAligned(void* data, int alignment)    
  63.     {    
  64.         // 又是一个经典算法, 参见<Hacker's Delight>    
  65.         return ((uintptr_t) data & (alignment - 1)) == 0;    
  66.     }    

注:

<Hacker's Delight>这是第一本试图揭开计算机运算神秘面纱的书,极其适合于编译器编写者、库开发者、反工程爱好者研读,将给大家展示一些鲜为人知但非常有意义的二进制编码技巧以及底层Algorithms技巧,其内容超级强悍。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值