I'm looking for a definitive answer (if indeed one exists) on how much memory should be allocated when creating a static chunks of shared memory via boost::interprocess
's managed_shared_memory
. Even official examples seem to allocate arbitrarily large chunks of memory.
Consider the following structure:
// Example: simple struct with two 4-byte fields
struct Point2D {
int x, y;
};
My initial reaction is that the necessary size would be 8 bytes, or sizeof(Point2D)
. This fails miserably when I attempt to construct an object, giving me seg-faults at runtime.
// BAD: 8 bytes is nowhere near enough memory allocated.
managed_shared_memory segment(create_only, "My shared memory", sizeof(Point2D));
What read/write operation is causing seg-faults? Stack operations? Temporarily allocations within segment.construct()
? How much overhead is necessary when allocating shared memory?
By trial-and-error I found that multiplying the size by 4 can work for the above structure, but falls apart when I start adding more fields to my struct
. So, that reeks of a bad hack.
Some might argue that "memory is cheap" in the modern PC, but I disagree with this philosophy and dislike allocating more than I need to, if I can avoid it. I dug around the Boost docs yesterday and couldn't find any recommendations. Here's to learning something new today!
From this paragraph of the documentation :
The memory algorithm is an object that is placed in the first bytes of a shared memory/memory mapped file segment.
Layout of the memory segment :
____________ __________ ____________________________________________
| | | |
| memory | reserved | The memory algorithm will return portions |
| algorithm | | of the rest of the segment. |
|____________|__________|____________________________________________|
The library has an extra memory overhead sitting at the beginning of the segment, thus occupying a few bytes of your requested size. According to this post and this post, this exact number of additional bytes cannot be determined :
You can't calculate it, because there are memory allocation bookeeping and fragmentation issues that change in runtime depending on your allocation/deallocation pattern. And shared memory is allocated by pages by the OS (4K on linux 64k on windows), so any allocation will be in practice allocated rounded to a page:
managed_shared_memory segment(create_only, "name", 20);
will waste the same memory as:
managed_shared_memory segment(create_only, "name", 4096);