Boost interprocess shared memory needs remap also get address again when one of processes truncates shared memory for dynamically growing size. Codes are below and in real cases consumer mapping
can get to know the new bound of memory created by productor trunc
for each time. However when larger memory created by trunc
, mapping will crash when input bigger offset to mapping
.
./trunc 10
./mapping
input 9, output is 9.
./trunc 10000,
input 9999 to mapping process, then segmentation fault.
trunc.cpp
#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
namespace bi = boost::interprocess;
int main(int argc, char* argv[]) {
bi::shared_memory_object shm(bi::open_or_create, "testshm", bi::read_write);
shm.truncate(sizeof(int) * std::atoi(argv[1]));
bi::mapped_region reg(shm, bi::read_write, 0);
int* p = (int*)reg.get_address();
for(std::size_t i = 0; i < std::atoi(argv[1]); ++i)
p[i] = i;
return 0;
}
mapping.cpp
#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
namespace bi = boost::interprocess;
int main(int argc, char* argv[]) {
bi::shared_memory_object shm(bi::open_only, "testshm", bi::read_only);
bi::mapped_region reg(shm, bi::read_only, 0);
int* p = (int*)reg.get_address();
do {
std::cout << "Please input offset:" << std::endl;
int offset;
std::cin >> offset;
std::cout << "Integer @" << offset << " is " << p[offset] << std::endl;
} while(true);
return 0;
}
It doesn't happen like that on my system.
Sadly, I can't show you live on Coliru (because shared memory is not supported), but you can perhaps retest with the following code:
#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
namespace bi = boost::interprocess;
static char const* const SHM_NAME = "sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4";
int main(int argc, char** argv) {
if (argc>1) {
bi::shared_memory_object shm(bi::open_or_create, SHM_NAME, bi::read_write);
shm.truncate(sizeof(int) * std::atoi(argv[1]));
bi::mapped_region reg(shm, bi::read_write);
int* p = reinterpret_cast<int*>(reg.get_address());
for(int i = 0; i < std::atoi(argv[1]); ++i)
p[i] = i;
std::cout << "Truncated and filled to " << reg.get_size() << "\n";
} else {
bi::shared_memory_object shm(bi::open_only, SHM_NAME, bi::read_only);
bi::mapped_region reg(shm, bi::read_only, 0);
size_t N = reg.get_size() / 4;
int const* p = reinterpret_cast<int const*>(reg.get_address());
size_t index;
while (std::cout << "Please input index: " && std::cin >> index) {
if (index < N)
std::cout << "Integer @" << index << " is " << p[index] << "\n";
else
std::cout << "Index " << index << " out of bounds [0.." << N << ")\n";
}
std::cout << "Bye\n";
}
}
It mostly changes minor things:
reinterpret_cast
trunc
and mapping
into a single fileI test it with:
./sotest 10
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"
Output:
Truncated and filled to 40
00000000: 0000 0000 0100 0000 0200 0000 0300 0000 ................
00000010: 0400 0000 0500 0000 0600 0000 0700 0000 ................
00000020: 0800 0000 0900 0000 ........
-rw-r--r-- 1 sehe sehe 40 jan 7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Index 999 out of bounds [0..10)
Please input index: Index 9999 out of bounds [0..10)
Please input index: Index 10000 out of bounds [0..10)
Please input index: Bye
sotest 10000
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"
Output:
Truncated and filled to 40000
00009bf0: fc26 0000 fd26 0000 fe26 0000 ff26 0000 .&...&...&...&..
00009c00: 0027 0000 0127 0000 0227 0000 0327 0000 .'...'...'...'..
00009c10: 0427 0000 0527 0000 0627 0000 0727 0000 .'...'...'...'..
00009c20: 0827 0000 0927 0000 0a27 0000 0b27 0000 .'...'...'...'..
00009c30: 0c27 0000 0d27 0000 0e27 0000 0f27 0000 .'...'...'...'..
-rw-r--r-- 1 sehe sehe 40000 jan 7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Integer @999 is 999
Please input index: Integer @9999 is 9999
Please input index: Index 10000 out of bounds [0..10000)
Please input index: Bye
sotest 10001
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"
Output:
Truncated and filled to 40004
00009c00: 0027 0000 0127 0000 0227 0000 0327 0000 .'...'...'...'..
00009c10: 0427 0000 0527 0000 0627 0000 0727 0000 .'...'...'...'..
00009c20: 0827 0000 0927 0000 0a27 0000 0b27 0000 .'...'...'...'..
00009c30: 0c27 0000 0d27 0000 0e27 0000 0f27 0000 .'...'...'...'..
00009c40: 1027 0000 .'..
-rw-r--r-- 1 sehe sehe 40004 jan 7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Integer @999 is 999
Please input index: Integer @9999 is 9999
Please input index: Integer @10000 is 10000
Please input index: Bye
If that gives different results on your system, let me know. Also, report platform details/versions used that case.