[英]Allocating an array of aligned struct
我正在嘗試分配一個結構數組,我希望每個結構都對齊到64個字節。
我嘗試了此操作(目前僅適用於Windows),但不起作用(我嘗試使用VS2012和VS2013):
struct __declspec(align(64)) A
{
std::vector<int> v;
A()
{
assert(sizeof(A) == 64);
assert((size_t)this % 64 == 0);
}
void* operator new[] (size_t size)
{
void* ptr = _aligned_malloc(size, 64);
assert((size_t)ptr % 64 == 0);
return ptr;
}
void operator delete[] (void* p)
{
_aligned_free(p);
}
};
int main(int argc, char* argv[])
{
A* arr = new A[200];
return 0;
}
assert ((size_t)this % 64 == 0)
斷言((size_t)this % 64 == 0)
模返回16)。 如果該結構僅包含簡單類型,則看起來可以工作,但是在包含std
容器(或其他一些std類)時會中斷。
難道我做錯了什么? 有沒有辦法做到這一點? (最好與c ++ 03兼容,但是在VS2012中可以使用的任何解決方案都可以)。
編輯:正如肖克瓦夫所暗示的,這有效:
A* arr = (A*)new std::aligned_storage<sizeof(A), 64>::type[200];
// this works too actually:
//A* arr = (A*)_aligned_malloc(sizeof(A) * 200, 64);
for (int i=0; i<200; ++i)
new (&arr[i]) A();
因此,它似乎與new []的使用有關...我很好奇是否有人有解釋。
我想知道為什么您需要如此巨大的對齊要求,而且還要在結構中存儲動態堆分配的對象 。 但是您可以這樣做:
struct __declspec(align(64)) A
{
unsigned char ___padding[64 - sizeof(std::vector<int>)];
std::vector<int> v;
void* operator new[] (size_t size)
{
// Make sure the buffer will fit even in the worst case
unsigned char* ptr = (unsigned char*)malloc(size + 63);
// Find out the next aligned position in the buffer
unsigned char* endptr = (unsigned char*)(((intptr_t)ptr + 63) & ~63ULL);
// Also store the misalignment in the first padding of the structure
unsigned char misalign = (unsigned char)(endptr - ptr);
*endptr = misalign;
return endptr;
}
void operator delete[] (void* p)
{
unsigned char * ptr = (unsigned char*)p;
// It's required to call back with the original pointer, so subtract the misalignment offset
ptr -= *ptr;
free(ptr);
}
};
int main()
{
A * a = new A[2];
printf("%p - %p = %d\n", &a[1], &a[0], int((char*)&a[1] - (char*)&a[0]));
return 0;
}
我沒有您的align_malloc和free函數,因此我提供的實現正在執行此操作:
輸出:
0x7fff57b1ca40 - 0x7fff57b1ca00 = 64
警告 :如果您的結構中沒有填充,則上述方案將破壞數據,因為我會將未對齊偏移量存儲在一個內部成員的構造函數將覆蓋的位置。 請記住,當您執行“ new X [n]”時,“ n”必須存儲在“某處”,因此在調用delete []時,將完成對析構函數的“ n”調用。 通常,它存儲在返回的內存緩沖區之前(new可能會分配所需的大小+ 4以存儲元素數)。 這里的方案避免了這種情況。
另一個警告 :因為C ++調用此運算符,並在其大小中包含一些額外的填充以存儲數組的元素數,所以您可能仍會在對象的返回指針地址中獲得“移位”。 您可能需要考慮它。 這就是std :: align的工作,它占用了額外的空間,像我一樣計算對齊方式並返回對齊的指針。 但是,你不能同時獲得在新的[]過載完成,這是因為()的新回國后這種情況發生了“計數存儲”轉變。 但是,您可以通過一次分配找出一次“計數存儲”空間,並在new []實現中相應地調整偏移量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.