c++ - structures - structure byte




malloc如何理解對齊? (4)

1)對齊所有對齊的最小公倍數。 例如,如果int需要4字節對齊,但指針需要8,則將所有內容分配到8字節對齊。 這導致一切都對齊。

2)使用size參數確定正確的對齊方式。 對於小尺寸,您可以推斷出類型,例如malloc(1) (假設其他類型的大小不是1)始終是char。 C ++ new具有類型安全的優點,因此總能以這種方式做出對齊決策。

以下摘錄自here

pw = (widget *)malloc(sizeof(widget));

分配原始存儲。 實際上,malloc調用分配的存儲空間足夠大並且適當地對齊以容納類型為widget 的對象

他還說,從草本植物中看到快速的pImpl ,他說:

對齊 。 任何內存對齊。 保證通過new或malloc動態分配的任何內存都可以正確地對齊任何類型的對象,但是沒有動態分配的緩衝區沒有這樣的保證

我對此感到好奇,malloc如何知道自定義類型的對齊方式?


malloc不知道它分配的內容,因為它的參數只是總大小。 它只是對齊一個對任何對像都安全的對齊方式。


在C ++ 11之前,通過使用最大對齊處理相當簡單,其中精確值是未知的,並且malloc / calloc仍然以這種方式工作。 這意味著malloc分配可以針對任何類型正確對齊。

錯誤的對齊可能導致根據標準的未定義行為,但我已經看到x86編譯器是慷慨的,只有較低的性能懲罰。

請注意,您還可以通過編譯器選項或指令調整對齊方式。 (例如VisualStudio的pragma包)。

但是當談到新的放置時 ,C ++ 11為我們帶來了一個名為alignofalignas的新關鍵字 下面是一些代碼,它顯示了編譯器最大對齊大於1時的效果。下面的第一個新位置自動為好,但不是第二個。

#include <iostream>
#include <malloc.h>
using namespace std;
int main()
{
        struct A { char c; };
        struct B { int i; char c; };

        unsigned char * buffer = (unsigned char *)malloc(1000000);
        long mp = (long)buffer;

        // First placment new
        long alignofA = alignof(A) - 1;
        cout << "alignment of A: " << std::hex << (alignofA + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofA)
        {
            mp |= alignofA;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex <<mp << endl;
        A * a = new((unsigned char *)mp)A;
        mp += sizeof(A);

        // Second placment new
        long alignofB = alignof(B) - 1;
        cout << "alignment of B: " <<  std::hex << (alignofB + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofB)
        {
            mp |= alignofB;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex << mp << endl;
        B * b = new((unsigned char *)mp)B;
        mp += sizeof(B);
}

我想這個代碼的性能可以通過一些按位操作來改進。

編輯:用逐位運算替換昂貴的模數計算。 仍然希望有人發現更快的東西。


對齊要求是遞歸的:任何struct的對齊只是其任何成員的最大對齊,這是遞歸理解的。

例如,假設每個基本類型的對齊等於其大小(通常這並不總是如此), struct X { int; char; double; } struct X { int; char; double; } struct X { int; char; double; }具有double的對齊,並且它將被填充為double的大小的倍數(例如4(int),1(char),3(padding),8(double))。 struct Y { int; X; float; } struct Y { int; X; float; } 具有X的對齊,這是最大的並且等於double的對齊,並且Y佈局:4(int),4(填充),16(X),4(浮點),4(填充) 。

(所有數字只是示例,可能與您的機器不同。)

因此,通過將其分解為基本類型,我們只需要知道一些基本的對齊,其中有一個眾所周知的最大。 C ++甚至定義了一個類型max_align_t其對齊方式最大的對齊方式。

所有malloc()需要做的是選擇一個該值的倍數的地址。





memory-alignment