...
In this non compliant code a struct of type A is allocated on the memory region of s.B. The problem is that A has a member of type unsigned long which on IA32 systems is required to be aligned to 4. However B is an array of unsigned chars inside S and is not aligned to 4. After the call to new, the pointer a is pointing to an unaligned memory address. Writing val into a->i can cause the program to terminate abnormally.
Code Block | ||
---|---|---|
| ||
int num = 5;
if (num * sizeof(SomeClass) > SIZE_MAX) {
/* handle error */
}
SomeClass *sc = static_cast<SomeClass*>(malloc(sizeof(SomeClass)*num));
if (sc == NULL) {
/* handle error */
}
// initialize sc array
// ...
// destroy sc
free(sc);
|
Compliant Solution
Code Block | ||
---|---|---|
| ||
#ifdef WIN32
#define ALIGN(X)_declspec(align(X))
#elif __GNUC__
#define ALIGN(X) __attribute__((aligned(X)))
#else
#define ALIGN(X)
#endif
struct A{
unsigned long i;
};
struct S{
unsigned char x;
unsigned char B[sizeof(A)];
}s;
int main()
{
A *a = new(&s.B[0]) A;
unsigned long val = 0xaabbccdd;
a->i = val;
return (0);
}
|
Compliant Solution
Vectors provide more safety and modularity than dynamically-allocated arrays
Code Block | ||
---|---|---|
| ||
{
int num = 5;
if (num * sizeof(SomeClass) > SIZE_MAX) {
/* handle error */
}
vector<SomeClass> sc(num);
// ...
} // sc automatically deleted
|
Compliant Solution (1)
The following is a compliant solution on a IA32 system using either GCC or Microsoft's Visual Studio. In this solution the macro ALIGN was added to ensure alignment when compiling with both Microsoft VS compiler and g++ . The ALIGN macro calls either _declspec(align(#)) or _attribute_((aligned(#)))) to enforce alignment on a particular variable. In this case it is used on B to make it aligned to 4, which is the alignment restriction for unsigned long.
...