2010-12-14 16 views
5

una riga di codice vale più di mille parole :) Ecco il mio problema:C++ allineamento memoria questione

/* 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); 

Posso aspettare che tutte le asserzioni passano su piattaforme con supporto SSE? Grazie.

MODIFICA. Risposta parziale Ho fatto qualche test con VS2008, GCC e ICC. Il compilatore MS ha allineato sia ptr e ptr2, ma GCC e ICC non sono riusciti ad allineare ptr2.

+0

Perché una serie di 20 Come? – John

+0

Appena fuori dalla mia testa. Stavo vagando, se anche ogni elemento dell'array è allineato. – watson1180

+2

Gli elementi di una matrice allocata correttamente sono garantiti dallo standard per essere allineati correttamente per il tipo in questione. Tuttavia, tale allineamento è un dettaglio di implementazione e potrebbe in teoria essere di un byte (cioè allineamento impacchettato). –

risposta

4

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

In altre parole, è possibile utilizzare lo standard per giustificare il vostro presupposto che dovrebbe funzionare, ma in pratica, può esplodere in faccia.

Visual C++ 6 non ha allineato doubles allocati tramite new correttamente, quindi ci si va.

+0

E i nuovi compilatori? GCC 4.xx e VS 2008? – watson1180

+1

Non conosco alcun compilatore che fornisca un allineamento di 16 byte con 'new' o' malloc', il che significa che in pratica gli asseriti falliranno. – jalf

+0

@jalf, sì, è quello che ho capito. Suppongo che sia "supportato" con C++ 0x, ma considerando che HeapAlloc garantisce 8 byte indirettamente (poiché l'opzione di default è l'allineamento di 8 byte per le strutture di dati di Windows), dubito che ciò accadrà presto. – MSN

1

C++ 0x fornisce un nuovo costrutto (in [meta.type.synop]20.7.6.6 altre trasformazioni):

std::aligned_storage<Length, Alignment> 

che è garantita sempre correttamente allineata il più Richiamo.

Il secondo parametro è facoltativo e il valore predefinito è il requisito più severo possibile (in modo che sia sempre sicuro non specificarlo, ma è possibile comprimere i tipi in modo più compatto se si è disposti a provare).

Oltre al bugs, il compilatore è tenuto a rispettare il requisito. Se non si dispone di C++ 0x, questo può essere trovato nel namespace tr1 o su Boost.

Sei l'unico che può provare che il compilatore particolare fa onore a questa richiesta :)

Nota: su gcc-4.3.2, esso è implementato come:

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

Gli oggetti vengono allocati con 'new' sebbene, che (di solito) non rispetti i requisiti di allineamento specifici. (Solitamente ti dà una memoria allineata di 8 byte, che è abbastanza buona per la maggior parte degli scopi) – jalf

+0

@jalf: ma lo standard impone che 'new' restituisca un pezzo di memoria adeguatamente allineato (da 3.7.4.1 [basic.std.dynamic .allocation] $ 2), a meno che non comprenda il * in modo che possa essere convertito in un puntatore di qualsiasi tipo di oggetto completo con un requisito di allineamento fondamentale (3.11) * e da 3.11 [base.align] $ 2 * Un allineamento fondamentale è rappresentato da un allineamento minore o uguale al più grande allineamento supportato dall'implementazione in tutti i contesti, che è uguale a alignof (std :: max_align_t) (18.2). * –

+0

... Pertanto I direi che se 'new' restituisce solo valori allineati a 8 byte e' std :: max_align_t' è superiore a 8, quindi l'implementazione non è conforme. –