2010-12-14 34 views
5

Một dòng mã có giá trị một ngàn chữ :) Dưới đây là vấn đề của tôi:C++ chỉnh bộ nhớ câu hỏi

/* Platform specific 16-byte alignment macro switch. 
    On Visual C++ it would substitute __declspec(align(16)). 
    On GCC it substitutes __attribute__((aligned (16))). 
*/ 
#define ALIGN_16 ... 

struct ALIGN_16 A {...}; 

A* ptr = new A; 
A* ptr2 = new A[20]; 

assert(size_t(ptr) % 16 == 0); 

for (int i=0; i<20; ++i) 
    assert(size_t(ptr2+i) % 16 == 0); 

assert(sizeof(A) % 16 == 0); 

Tôi có thể hy vọng rằng tất cả khẳng định vượt qua trên nền tảng với sự hỗ trợ SSE? Cảm ơn bạn.

EDIT. Câu trả lời một phần. Tôi đã làm một số thử nghiệm với VS2008, GCC và ICC. Trình biên dịch MS đã căn chỉnh cả hai ptrptr2, nhưng GCC và ICC không thể căn chỉnh ptr2.

+0

Tại sao một mảng của 20 Như? – John

+0

Chỉ cần ra khỏi đầu của tôi. Tôi đã lang thang, nếu mọi phần tử của mảng cũng được căn chỉnh. – watson1180

+2

Các phần tử của một mảng được phân bổ phù hợp được đảm bảo theo tiêu chuẩn để được căn chỉnh phù hợp với loại được đề cập. Tuy nhiên, sự liên kết đó là một chi tiết thực hiện và có thể theo lý thuyết là một byte (tức là sự sắp xếp được đóng gói.) –

Trả lời

4

Is there any guarantee of alignment of address return by C++'s new operation?

Nói cách khác, bạn có thể sử dụng tiêu chuẩn để biện minh cho giả thuyết của mình rằng nó sẽ làm việc, nhưng trong thực tế, nó có thể thổi lên trong khuôn mặt của bạn.

Visual C++ 6 không căn chỉnh doubles được phân bổ qua new đúng cách, vì vậy bạn đã đi.

+0

Còn các trình biên dịch mới hơn thì sao? GCC 4.xx và VS 2008? – watson1180

+1

Tôi không biết bất kỳ trình biên dịch nào cung cấp sự liên kết 16 byte với 'new' hoặc' malloc', có nghĩa là trong thực tế, các xác nhận sẽ thất bại. – jalf

+0

@ jalf, yup, đó là những gì tôi đã tìm. Tôi cho rằng nó được "hỗ trợ" với C++ 0x, nhưng xem xét HeapAlloc bảo đảm 8 byte gián tiếp (vì tùy chọn đóng gói mặc định là liên kết 8 byte cho cấu trúc dữ liệu cửa sổ), tôi nghi ngờ điều này sẽ sớm xảy ra. – MSN

1

C++ 0x cung cấp một cấu trúc mới (trong [meta.type.synop]20.7.6.6 biến đổi khác):

std::aligned_storage<Length, Alignment> 

thức bảo đảm đến được luôn đặt đúng cách càng xa càng Tôi gọi lại.

Tham số thứ hai là tùy chọn và mặc định là yêu cầu nghiêm ngặt nhất có thể (để luôn chính xác, nhưng bạn có thể đóng gói gọn nhẹ hơn nếu bạn sẵn sàng thử).

Ngoài bugs, trình biên dịch được ràng buộc để tôn trọng yêu cầu. Nếu bạn không có C++ 0x, điều này có thể được tìm thấy trong không gian tên tr1 hoặc trên Boost.

Bạn là người duy nhất có thể kiểm tra rằng trình biên dịch cụ thể của bạn không tôn trọng yêu cầu này :)

Lưu ý: trên gcc-4.3.2, nó được thực hiện như sau:

template<std::size_t _Len, std::size_t _Align = /**/> 
struct aligned_storage 
{ 
    union type 
    { 
    unsigned char __data[_Len]; 
    struct __attribute__((__aligned__((_Align)))) { } __align; 
    }; 
}; 
+0

Các đối tượng được phân bổ bằng 'mới' mặc dù, thường (thường) không tôn trọng các yêu cầu căn chỉnh cụ thể. (Nó thường chỉ cung cấp cho bạn bộ nhớ liên kết 8 byte, đủ tốt cho hầu hết các mục đích) – jalf

+0

@jalf: nhưng các yêu cầu tiêu chuẩn rằng 'new' trả về một phần bộ nhớ phù hợp (từ 3.7.4.1 [basic.std.dynamic .allocation] $ 2), trừ khi tôi không hiểu * để nó có thể được chuyển đổi thành con trỏ của bất kỳ loại đối tượng hoàn chỉnh nào với yêu cầu căn chỉnh (3.11) * và từ 3.11 [cơ bản.align] $ 2 * Một căn chỉnh được đại diện bởi một liên kết nhỏ hơn hoặc bằng sự liên kết lớn nhất được hỗ trợ bởi việc thực hiện trong tất cả các bối cảnh, bằng alignof (std :: max_align_t) (18.2). * –

+0

... Do đó tôi sẽ nói rằng nếu 'new' chỉ trả về các giá trị liên kết 8 byte và' std :: max_align_t' vượt trội hơn 8, thì việc thực thi không phù hợp. –