2012-01-31 59 views
12

對齊mallocposix_memalign,沒關係,但對齊的realloc呢? realloc是否保留對齊方式或如何確保重新分配的內存具有相同的對齊方式?假設Linux和x86_64。是否realloc保持posix_memalign的內存對齊?

+2

不適用 - 如果您需要特殊的對齊方式,例如對於SIMD數據,則不要使用realloc。 – 2012-01-31 10:52:59

+0

所以,如果我需要「對齊realloc」,我必須釋放和posix_memalign新的記憶,對吧? – Cartesius00 2012-01-31 10:54:10

+1

是的 - 如果你真的想,你甚至可以實現你自己的'posix_memrealloc'。 – 2012-01-31 10:55:45

回答

15

否,從posix_memalign返回的存儲器上的realloc不能由ISO或POSIX保證保持相同的對齊。 A realloc可能只是在同一地址展開當前塊,但它也可能將塊移到一個不同於原始對齊的不同地址。

如果你想要相同的對齊,最好分配另一個塊並複製數據。

不幸的是,在單一UNIX規範中也沒有posix_memalign_realloc函數。

如果你不想去通過複製數據時間的麻煩,你可以試試realloc(一),如果不符合預期的,對準,然後,然後才請致電posix_memalign以獲得正確對齊的地址並將數據複製到那裏,完成後釋放舊地址。

這可能導致:

  • 零個拷貝(如果當前塊可以就地進行擴展);
  • 一個副本(如果realloc副本,但恰好給你一個正確對齊的塊);或
  • 兩個副本(如果realloc副本,然後你還必須複製,由於錯位)。

可能根據底層的內存管理實現也會導致比指示更少的複製。例如,「複製」可能只涉及重新映射內存塊,而不是物理地移動數據。

所以你可能想保留一些統計數據,看看這個方案是否值得。


(一)請記住,無論是POSIX也不Linux手冊頁指定與否,你甚至可以傳遞這些指針realloc,只是你可以將它們傳遞給free

然而,基於當前的GNU庫的源代碼,它似乎工作,雖然這並不能保證它會繼續在今後的工作中:-)

我擔心的是,它通常會分配內存(標準對齊)並且傳遞一個偏移地址(即,不是分配的實際地址,而是一個超出該地址的字節),其中free足夠智能以在編譯它的魔法之前變回實際地址。

這樣做的一種方法是將實際地址存儲在返回地址之前,儘管這當然會導致即使對於正常分配也會造成浪費。

在這種情況下,free可能已經做出智能(因爲規格說,它必須能夠處理由posix_memalign所做的分配),但realloc可能沒有被賦予相同的智能(由於文檔是對此事沉默)。

但是,基於GNU glibc 2.14.1,它實際上分配了比所需內存更多的內存,然後與場地一起擺弄前置空間和後置空間,以便返回的地址是「真實」地址,可由freerealloc使用。

但是,如上所述,文檔不能保證這一點。

+0

這個答案在一個重要方面不正確:即使內存區域移動,realloc通常也不會複製。我認爲如果當前內存地址沒有足夠的空間來擴展緩衝區 - 頁面會被重新映射以避免複製。所以它會是零份,零份,一份。 – 2016-05-05 21:16:15

+0

@RafaelBaptista,你在*標準中混淆了一些*實現*。*標準(ISO/POSIX)中沒有任何*規定了如何在封面下發生。然而,在我回答假設Linux將這個領域縮小了一點之後(但是由於Linux運行在各種各樣硬件上,並且MMU選項可能非常多樣),這個問題似乎已經改變了。將調整答案以適應。 – paxdiablo 2016-05-06 02:22:54

1

realloc與malloc行爲相同,因此realloc返回的內存具有與malloc相同的對齊約束。

0

如果您查看realloc的glibc源代碼,它會直接調用malloc。所以內存和malloc一樣。

+0

對不起,我應該補充。在源代碼中,如果原始malloc'd內存已經指向的位置有額外的堆空間,那麼它只是在原始分配大小末尾分配額外的堆而不調用malloc。這顯然不會改變路線。 – 2012-01-31 10:58:58