Do not invoke realloc()
to modify the size of allocated storage objects that has have stricter alignment requirements than those normally provided guaranteed by malloc()
. Storage allocated by a call to the standard aligned_alloc()
function, for example, can have stricter than normal alignment requirements. The C standard mandates requires only that any a pointer returned by mallocrealloc()
must be suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement (storage allocated by a call to the C Standard aligned_alloc()
function, for example.)
Noncompliant Code Example
This noncompliant code example returns a pointer to allocated memory that has been aligned to a 4096-byte boundary. If the resize
argument to the realloc()
function is larger than the space object referenced by ptr
, then realloc()
will allocate new memory that is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement , but may not preserve the stricter alignment requirements of the original spaceobject.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> void func(void) { size_t resize = 1024; size_t alignment = 1 << 12; int *ptr; int *ptr1; if (NULL == (ptr = (int *) aligned_alloc(alignment, sizeof(int))) == NULL) { /* Handle error */ } if (NULL == (ptr1 = (int *) realloc(ptr, resize)) == NULL) { /* Handle error */ } } |
...
This compliant solution allocates resize
bytes of new memory with the same alignment as the old memory, copies the original memory content, and then frees the old memory:. This solution has implementation-defined behavior because it depends on whether extended alignments in excess of _Alignof (max_align_t)
are supported and the contexts in which they are supported. If not supported, the behavior of this compliant solution is undefined.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> #include <string.h> void func(void) { size_t resize = 1024; size_t alignment = 1 << 12; int *ptr; int *ptr1; if (NULL == (ptr = (int *)aligned_alloc(alignment, sizeof(int))) == NULL) { /* Handle error */ } if (NULL == (ptr1 = (int *)aligned_alloc(alignment, resize)) == NULL) { /* Handle error */ } if (NULL == (memcpy(ptr1, ptr, sizeof(int)) == NULL) { /* Handle error */ } free(ptr); } |
Compliant Solution (Windows)
Windows defines the _aligned_malloc()
function to allocate memory on a specified alignment boundary. The _aligned_realloc()
[MSDN] can be used to change the size of this memory. This compliant solution demonstrates one such usage:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <malloc.h> void func(void) { size_t alignment = 1 << 12; int *ptr; int *ptr1; /* Original allocation */ if (NULL == (ptr = (int *)_aligned_malloc(sizeof(int), alignment)) == NULLalignment))) { /* Handle error */ } /* Reallocation */ if (NULL == (ptr1 = (int *)_aligned_realloc(ptr, 1024, alignment)) == NULLalignment))) { _aligned_free(ptr); /* Handle error */ } _aligned_free(ptr1); } |
Note that the size the size
and alignment
arguments for _aligned_malloc()
are provided in reverse order of the C Standard aligned_alloc()
function.
...
Bibliography
[ISO/IEC 9899:2011] | Subclause 77.22.3.1, "The aligned_alloc Function" |
[MSDN] | aligned_malloc() |
...