如何僅使用標準庫分配對齊的內存?

在工做面試中,我剛剛完成了一次測試,一個問題困擾着我,甚至使用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);
相關文章
相關標籤/搜索