2013-06-29 63 views
4

malloc()文檔說,返回的指針適合任何類型的變量。在我的系統中,long double的大小爲12,但malloc()返回的一些指針在8字節邊界上對齊,而不是12(ptr%12給出4)。任何人都可以指出我在這裏錯過了什麼?提前致謝。Malloc和未對齊的內存

+0

你從哪裏閱讀了關於malloc返回對齊的內存? –

+3

在手冊頁中。請參閱此處的返回值http://linux.die.net/man/3/malloc。還是我誤解了一些東西? – user44990

+7

12字節長的雙打不需要12字節對齊。 –

回答

5

很明顯,long double不需要對齊到12個字節。在您的系統上,原始C類型的最大對齊爲double的8個字節。不要混淆對齊和大小 - 而許多較小的(尤其是原始的)類型必須自然對齊 - 即按照自己的大小對齊 - 這對於較大的數據類型來說是禁止的(思考碎片),並且不會使硬件。

+0

哪些較大的類型? – Sebivor

+0

@undefinedbehaviour:'struct's。 –

+0

@MatteoItalia ...但結構的第一個成員必須適合對齊或發生未定義的行爲。這是沒有意義的。你知道可以打開英特爾機器上的總線錯誤檢查嗎?也許你應該在斷言之前驗證這一點...... – Sebivor

3

gcc Linux和x86您有:

sizeof (long double) == 12

gcc Linux和x64您有:

sizeof (long double) == 16

的ABI對齊的要求x64long double16-bytes。對於x86,沒有類型需要超過8字節的對齊方式。

尊重該glibcmalloc返回存儲器的對象與8 -bytes上32-bit系統對準並上16 -bytes爲64位系統對準。

glibc DOC:

確定malloc給你保證對齊,以便它可以保存任何類型的數據塊。在GNU系統上,大多數系統的地址總是8的倍數,64位系統的地址總是16的倍數。

0

malloc將返回存儲器的任何類型的適當對準,因爲通常它返回指針被轉換爲任意類型的指針和這樣的轉換是典型地(讀:無限接近的時間的100%)無-OP。對於任何體系結構和編譯器來說,任何類型的最大對齊是一個常量,通常它是所有基本類型對齊的最大值。對象的大小應該是其對齊的倍數。有時這種要求必須通過向對象內的值添加填充來滿足。

如果您的編譯器足夠現代化,它將支持_Alignof,類似於sizeof,因此您可以使用小程序檢查實際對齊方式。我認爲在你的架構上最大對齊是4.如果malloc總是返回由8對齊的地址,那麼它仍然符合。對於malloc來說,並不少見的是一個對齊類型的最大對齊的倍數。

0

你錯過了一個類型的大小必須是其對齊的倍數(它受到實際硬件的限制),它們不必相同。

long double情況下,這轉化爲

_Alignof (long double) == 4 
sizeof (long double) == 12 

用gcc/x86和

_Alignof (long double) == 16 
sizeof (long double) == 16 

用gcc/64,其中,在這兩種情況下long double具有80位的擴展精度。

如果我們沒有受到限制對齊,最自然的,我們會最終

sizeof (long double) == 10 

在對齊的情況下,我們會要麼不得不去爲2的比對(我們不要」出於效率原因),或者向數組引入填充,以便元素正確對齊。這違反了C語言的語義,數組的大小是其元素大小和數量的乘積。

3

在任何理智的cpu架構上,對於大小爲12的對象,最大可能的對齊要求是4.對齊要求必須是2的冪,該大小等於該類型的大小。事實上,這給出了非常差的對齊方式(跨越緩存行甚至頁面的對象!),這就是爲什麼x86_64 ABI將long double的大小更改爲16:這樣就有可能使它不會跨越任何邊界。