如何仅使用标准库分配对齐的内存?

在工做面试中,我刚刚完成了一次测试,一个问题困扰着我,甚至使用Google做为参考。 我想看看StackOverflow小组能够作什么: 面试

memset_16aligned函数须要一个16字节对齐的指针传递给它,不然它将崩溃。 函数

a)您将如何分配1024个字节的内存,并将其与16个字节的边界对齐?
b)执行memset_16alignedmemset_16aligned内存。 测试

{    
   void *mem;
   void *ptr;

   // answer a) here

   memset_16aligned(ptr, 0, 1024);

   // answer b) here    
}

#1楼

long add;   
mem = (void*)malloc(1024 +15);
add = (long)mem;
add = add - (add % 16);//align to 16 byte boundary
ptr = (whatever*)(add);

#2楼

您还能够添加一些16个字节,而后经过在指针下面添加(16-mod)将原始ptr推向16位对齐: 优化

main(){
void *mem1 = malloc(1024+16);
void *mem = ((char*)mem1)+1; // force misalign ( my computer always aligns)
printf ( " ptr = %p \n ", mem );
void *ptr = ((long)mem+16) & ~ 0x0F;
printf ( " aligned ptr = %p \n ", ptr );

printf (" ptr after adding diff mod %p (same as above ) ", (long)mem1 + (16 -((long)mem1%16)) );


free(mem1);
}

#3楼

在16字节和15字节计数的填充前沿上,您须要添加以得到N对齐的实际数字是max(0,NM) ,其中M是内存分配器的天然对齐(均为2的幂)。 spa

因为任何分配器的最小内存对齐方式都是1个字节,所以15 = max(0,16-1)是一个保守的答案。 可是,若是您知道内存分配器将为您提供32位int对齐的地址(这是很常见的),则可使用12做为填充。 设计

对于此示例而言,这并不重要,可是在具备12K RAM的嵌入式系统中,每一个int保存的计数都很是重要。 指针

若是您实际上要尝试保存全部可能的字节,则实现它的最佳方法是将其做为宏,以便您能够将其做为本机内存对齐。 一样,这可能仅对须要保存每一个字节的嵌入式系统有用。 code

在下面的示例中,在大多数系统上,对于MEMORY_ALLOCATOR_NATIVE_ALIGNMENT ,值1很好,可是对于咱们的具备32位对齐分配的理论嵌入式系统,如下内容能够节省一小部分宝贵的内存: 内存

#define MEMORY_ALLOCATOR_NATIVE_ALIGNMENT    4
#define ALIGN_PAD2(N,M) (((N)>(M)) ? ((N)-(M)) : 0)
#define ALIGN_PAD(N) ALIGN_PAD2((N), MEMORY_ALLOCATOR_NATIVE_ALIGNMENT)

#4楼

特定于MacOS X: 技巧

  1. 用malloc分配的全部指针均对齐16个字节。
  2. 支持C11,所以您只需调用aligned_malloc(16,大小)便可。

  3. MacOS X会在启动时针对memset,memcpy和memmove选择针对单个处理器进行了优化的代码,而且该代码使用了您从未据说过的技巧来使其快速运行。 memset运行速度比任何手写的memset16快99%,这使整个问题毫无心义。

若是您想要100%可移植的解决方案,那么在C11以前没有。 由于没有可移植的方法来测试指针的对齐方式。 若是没必要100%可移植,则可使用

char* p = malloc (size + 15);
p += (- (unsigned int) p) % 16;

假定将指针转换为unsigned int时,指针的对齐方式存储在最低位。 转换为unsigned int会丢失信息并由实现定义,但这不要紧,由于咱们不会将结果转换回指针。

固然,最糟糕的部分是原始指针必须保存在某个地方才能用它调用free()。 因此总的来讲,我真的会怀疑这种设计的智慧。


#5楼

若是存在约束,则不能浪费单个字节,则此解决方案有效:注意:在某些状况下,它能够无限执行:D

void *mem;  
   void *ptr;
try:
   mem =  malloc(1024);  
   if (mem % 16 != 0) {  
       free(mem);  
       goto try;
   }  
   ptr = mem;  
   memset_16aligned(ptr, 0, 1024);
相关文章
相关标签/搜索