Labels

Wednesday, June 16, 2010

Pragma pack

Pragma pack
Syntax:

#pragma pack [n]

Where n can equal 1, 2, 4, 8, or 16 and indicates, in bytes, the maximum alignment of class fields having non-class types. If n is not specified, maximum alignment is set to the default value.
Description:
This pragma allows you to specify the maximum alignment of class fields having non-class types. The alignment of the whole class is then computed as usual, the alignment of the most aligned field in the class.

NOTE: The result of applying #pragma pack n to constructs other than class definitions (including struct definitions) is undefined and not supported. For example:

#pragma pack 1
int global_var; // Undefined behavior: not a class definition

void foo() { // Also undefined
}

Usage
The pack pragma may be useful when porting code between different architectures where data type alignment and storage differences are of concern. Refer to the following examples:

* Basic Example
* Template Example
* Handling Unaligned Data
* Implicit Access to Unaligned Data

Refer also to Default Data Storage and Alignment.
Basic Example
The following example illustrates the pack pragma and shows that it has no effect on class fields unless the class itself was defined under the pragma.

Example 1:

struct S1 {
char c1; // Offset 0, 3 bytes padding
int i; // Offset 4, no padding
char c2; // Offset 8, 3 bytes padding
}; // sizeof(S1)==12, alignment 4

#pragma pack 1

struct S2 {
char c1; // Offset 0, no padding
int i; // Offset 1, no padding
char c2; // Offset 5, no padding
}; // sizeof(S2)==6, alignment 1

// S3 and S4 show that the pragma does not affect class fields
// unless the class itself was defined under the pragma.
struct S3 {
char c1; // Offset 0, 3 bytes padding
S1 s; // Offset 4, no padding
char c2; // Offset 16, 3 bytes padding
}; // sizeof(S3)==20, alignment 4

struct S4 {
char c1; // Offset 0, no padding
S2 s; // Offset 1, no padding
char c2; // Offset 7, no padding
}; // sizeof(S4)==8, alignment 1

#pragma pack

struct S5 { // Same as S1
char c1; // Offset 0, 3 bytes padding
int i; // Offset 4, no padding
char c2; // Offset 8, 3 bytes padding
}; // sizeof(S5)==12, alignment 4

Template Example
If the pragma is applied to a class template, every instantiation of that class is influenced by the pragma value in effect when the template was defined.

CAUTION: The alignment of specializations and partial specializations of templates is undefined and unsupported if either the primary template or the specialization is under the influence of a #pragma pack directive.

Example 2:

#pragma pack 1

template
struct ST1 {
char c1;
T x;
char c2;
};

#pragma pack

ST1 obj; // Same layout as S2 in the prior example

template <> // Explicit specialization
struct ST1 {
char c1;
char c2;
}; // Undefined (unsupported) behavior
// ST1 was defined under a #pragma pack 1
// directive.

Handling Unaligned Data
Direct access to unaligned class fields is handled automatically by HP aC++. However, this results in slower access times than for aligned data.

Indirect access (through pointers and references) to unaligned class fields is also handled automatically.

CAUTION:If you take the address of a data field and assign it to a pointer, it is not handled automatically and is likely to result in premature termination of the program if not handled appropriately. For example:

Example 3:

#include
#pragma pack 1
struct S1 {
char c1;
int i;
char c2;
};
#pragma pack
int main() {
S1 s;
S1 *p = &s;
printf("%d\n", s.i); // OK
printf("%d\n", p->i); // OK
int *ip = &p->i; // Undefined behavior
// Likely Abort unless compiled with +u1
// The address of a reference (*ip) is
// assigned to an int pointer.
printf("%d\n", *ip);
}

To enable indirect access to unaligned data that has been assigned to another type, either of the following two options are available.

* Compile with the +unum option, to generate safe but less efficient code for every indirect access to memory.

* Link in the library libhppa.a (part of the fileset ProgSupport.PROG-AUX) and arm the appropriate signal handler with a call to allow_unaligned_data_access(). This causes every signal due to unaligned access to be intercepted and handled as expected. It also creates significant run-time overhead for every access to unaligned data, but does not impact access to aligned data.

Implicit Access to Unaligned Data
Calls to non-static member functions require that an implicit this pointer be passed to these functions, which can then indirectly access data through this implicit parameter. If such an access is to unaligned data, the situation in the prior Example 3 occurs.

Furthermore, virtual function calls often require indirect access to a hidden field of a class that could be unaligned under the influence of the #pragma pack directive.

If passing the address of a field to code not compiled with the +u1 option, consider the following example. Unless compiled with -DRECOVER on the command-line and linked with /usr/lib/libhppa.a, Example 4 is likely to prematurely terminate with a bus error.

Example 4:

#include
#ifdef RECOVER
extern "C" void allow_unaligned_data_access();
#endif

#pragma pack 1

struct PS1 {
PS1();
~PS1();
private:
char c;
int a;
};

#pragma pack

PS1::PS1(): a(1) { // There appears to be no pointer, but there
// is an unaligned access, possibly through "this."
printf("In constructor.\n");
}

PS1::~PS1() {
a = 0; // Misaligned access, possibly though "this"
printf("In destructor.\n");
}

int main() {
#if defined(RECOVER)
allow_unaligned_data_access();
#endif
PS1 s;
}

No comments:

Post a Comment