Problemi di compressione del compilatore C

I livelli di compressione influiscono sul layout di memoria dei tipi sia per MIDL che per il compilatore Microsoft C/C++ nello stesso modo. Negli ambienti di compilazione Microsoft, ad esempio l'ambiente di compilazione definito da VC++ o Platform Software Development Kit (SDK), il livello di compressione predefinito per i compilatori MIDL e C/C++ è lo stesso; il livello di compressione predefinito per gli ambienti di compilazione Windows a 32 bit e a 64 bit è 8.

Allineamento naturale

Per i tipi in memoria, l'allineamento predefinito corrisponde all'allineamento naturale.

  • Un tipo di base, ad esempio short, float e __int64, e un puntatore viene allineato naturalmente se la relativa rappresentazione inizia in corrispondenza di un indirizzo che ne forma le dimensioni. Tutti i tipi di base attualmente supportati hanno dimensioni pari a 1, 2, 4 o 8. I puntatori hanno dimensioni pari a 4 in ambienti a 32 bit e 8 in ambienti a 64 bit.
  • Un tipo composto viene allineato naturalmente se ognuno dei relativi componenti è allineato naturalmente rispetto all'inizio del tipo e se non sono presenti spazi superflui (spaziatura interna) tra i componenti. I componenti composti, ad esempio campi o elementi, vengono ricorsi a componenti di tipo base o puntatore.

Una semplice regola per ricordare questo comportamento è che l'allineamento naturale di un tipo è uguale agli allineamenti più grandi dei relativi componenti.

Esiste una connessione tra le dimensioni di allineamento e memoria di un tipo in linguaggi come C o C++ e IDL come espresso dalla dimensione dell'operatoreof(). La dimensione è un multiplo dell'allineamento (il multiplo minimo che si estende sul tipo). Segue da una rappresentazione di matrice in memoria.

L'allineamento naturale è importante perché l'accesso ai dati non allineati può causare un'eccezione in alcuni sistemi. I dati possono essere contrassegnati per una manipolazione sicura quando non sono allineati, ma in genere comportano una penalità di velocità sostanziale in alcune piattaforme.

Nota

In memoria, gli oggetti di tipi con un allineamento naturale di n vengono sicuramente allineati correttamente quando vengono posizionati in corrispondenza di indirizzi multipli di n.

 

Compressione e allineamento

Se si specifica un livello di compressione maggiore dell'allineamento naturale di un tipo, l'allineamento del tipo non cambia. Se si specifica un livello di compressione inferiore rispetto all'allineamento naturale, l'allineamento del tipo viene ridotto al livello di compressione. Di conseguenza, i tipi compressi possono essere inseriti in memoria a indirizzi multipli del livello di compressione (allineamento ridotto) senza causare un disallineamento. Ciò influisce sia sui tipi semplici che sui tipi di componente. Per i tipi composti, il layout interno del tipo può essere influenzato, perché l'allineamento ridotto dei componenti può modificare le dimensioni della spaziatura interna necessaria per l'allineamento corretto dei componenti, riducendo così le dimensioni del tipo.

Una semplice regola per ricordare questo comportamento è che il nuovo allineamento di un tipo compresso è il più piccolo del livello di compressione e il suo allineamento naturale. La dimensione del tipo è un multiplo del nuovo allineamento. L'operatore sizeof() restituisce le dimensioni ridotte per i tipi compressi.

Ad esempio, con il livello di compressione 2 un lungo diventa allineato a 2, e pertanto può essere posizionato in qualsiasi indirizzo pari, non solo agli indirizzi che sono un multiplo di 4 come sarebbe il caso con l'allineamento naturale. Una struttura con un corto e un lungo, compresso a 2, non ha bisogno del divario interno tra il corto e il successivo lungo che era necessario per l'allineamento naturale; pertanto, non solo è la struttura ora allineata a 2, ha anche la sua dimensione ridotta da 8 a 6.

Si consideri ad esempio un tipo composto costituito da un carattere a 1 byte, un numero intero di 4 byte lungo e un carattere a 1 byte:

struct mystructtype 
{    
    char c1;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
    long l2;  /* requires 4 bytes */
    char c3;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
 } mystruct;

Questa struttura è naturalmente allineata a 4 e ha la dimensione naturale di 12.

Per il livello di compressione 4 o superiore, la struttura mystruct è allineata a 4 ed sizeof(struct mystructtype) è uguale a 12. La struttura sarà disallineata se si trova in memoria in un indirizzo che non è un multiplo di 4.

Per il livello di compressione 2, la struttura è allineata a 2 e la dimensione è 8. La struttura compressa con il livello 2 non sarà allineata se si trova in memoria in un indirizzo che non è un multiplo di 2.

Per il livello di compressione 1, la struttura è allineata a 1 e la dimensione è 6. La struttura compressa con il livello 1 può essere posizionata ovunque senza causare un errore di disallineamento.

/Zp

/branco