Provide raw buffers with user-specified size and alignment.
More...
Namespaces |
namespace | bsls |
Detailed Description
- Outline
-
-
- Purpose:
- Provide raw buffers with user-specified size and alignment.
-
- Classes:
-
- See also:
- Component bsls_objectbuffer, Component bsls_alignmenttotype
-
- Description:
- This component provides a templated buffer type with a user-specified compile-time size and user-specified alignment. The user instantiates
bsls::AlignedBuffer
with specific size and alignment requirements, and then uses that memory as needed. If an alignment is not specified at template instantiation, then the buffer object is maximally aligned.
- Typically,
bsls::AlignedBuffer
is used in situations where it is desirable to allocate a block of properly-aligned raw memory from somewhere other than the heap, e.g., on the stack or within an aggregate object, including within a union. It is a convenient way to create a small heap from which one or more objects are allocated at run-time.
-
- Single-Object Buffers:
- Although, for a given type
T
, bsls::AlignedBuffer<sizeof(T), bsls::AlignmentFromType<T>VALUE>
will produce a buffer properly sized and aligned to hold a T
object, it is simpler and clearer to use bsls::ObjectBuffer<T>
for this purpose. See the bsls_objectbuffer
component for more information.
-
- Stack Alignment:
- On platforms with 32-bit words, there is usually no efficiency gain by using more than 4-byte alignment. Yet some compilers use 8-byte alignment for
long long
or double
, presumably so that the code will run faster on a future 64-bit CPU. The program loader, however, has no reason to presume more than 4-byte alignment when allocating the program stack. This can result in stack objects appearing to be misaligned relative to the alignments computed by this component. This is not a bug in either this component nor in the compiler, but it is somewhat surprising. We have seen this behavior on the MS VC++ 7 platform. See also the "Surprises and
Anomalies" section in bsls_alignmentfromtype.h
.
-
- Known issues:
- On all versions of the Microsoft compiler prior to MSVC 14.0 (2015), passing
AlignedBuffer
or an object containing AlignedBuffer
as a by-value function argument would lead to C2719 error (see https://msdn.microsoft.com/en-us/library/373ak2y1.aspx). In versions 14.10 (2017) through 16.8 (2019) it can trigger a compiler bug leading to crashes due to the destructor being invoked with an incorrect this
pointer. This bug has been observed only building for x86 (32-bit) platform in Debug mode (specifically with /Od /Ob0 flags), e.g.: See DRQS 151904020 for more details.
- This was fixed my Microsoft in MSVC 2019 version 16.9, for details see: https://developercommunity.visualstudio.com/t/incorrect-code-gen-missing-error/831543
-
- Usage:
- The
allocateFromBuffer
function below uses an aligned buffer as a small heap from which objects can be allocated. We choose int
alignment (4-byte alignment) for our buffer because the objects we are allocating are composed of char
, short
, and int
values only. If no alignment were specified, the buffer would be maximally aligned, which could be wasteful on some platforms. const int MY_ALIGNMENT = bsls::AlignmentFromType<int>::VALUE;
bsls::AlignedBuffer<1000, MY_ALIGNMENT> my_AllocBuffer;
const char* my_AllocEnd = my_AllocBuffer.buffer() + 1000;
char *my_AllocPtr = my_AllocBuffer.buffer();
static void *allocateFromBuffer(int size)
{
if (size > my_AllocEnd - my_AllocPtr)
return 0;
void *result = my_AllocPtr;
my_AllocPtr += size;
if (size % MY_ALIGNMENT) {
my_AllocPtr += MY_ALIGNMENT - size % MY_ALIGNMENT;
}
assert(0 == size_t(my_AllocPtr) % MY_ALIGNMENT);
return result;
}
Below, we use our allocation function to allocate arrays of char
, short
, and user-defined Object
types from the static buffer. Note that our Object
structure is composed of members that have alignment requirements less than or equal to int
s alignment requirements. struct Object {
char d_c;
short d_s;
int d_i;
};
int main()
{
char *charPtr = (char *) allocateFromBuffer(3 * sizeof(char));
assert(0 == size_t(charPtr) % MY_ALIGNMENT);
short *shortPtr = (short *) allocateFromBuffer(3 * sizeof(short));
assert(0 == size_t(shortPtr) % MY_ALIGNMENT);
Object *objPtr = (Object *) allocateFromBuffer(3 * sizeof(Object));
assert(0 == size_t(objPtr) % MY_ALIGNMENT);
if (!charPtr || !shortPtr || !objPtr) {
fprintf(stderr, "Global buffer is not large enough.\n");
return -1;
}
return 0;
}