增长 managed_shared_memory 段后出现段错误
Segmentation fault after growing a managed_shared_memory segment
我正在研究 boost 库的共享内存部分,为更大的项目做准备。我需要一个共享内存段,在初始化时我不一定知道它的大小,所以我的计划是增加这个段。
我的初始实现有一个 boost::interprocess::vector
存储在共享内存中。当我向向量中添加值时,如果向量的大小超过了段(抛出 bad_alloc
异常),我会增大段。这通常会工作几次,直到出现分段错误。
不确定这是否有帮助,在此实施之前,我的代码会在调用 managed_shared_memory::grow()
方法时挂起。经过一些谷歌搜索后,我发现这可能是因为该段仍然映射到主进程。当前错误发生在我将 remover
结构移出构造函数之后。现在,代码没有挂起,但它确实出现了段错误。
代码如下:
#include <iostream>
#include <exception>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
using namespace boost::interprocess;
static const std::string SHMEM_NAME = "MySharedMemorySegment";
typedef allocator<int, managed_shared_memory::segment_manager> IntAllocator;
typedef vector<int, IntAllocator> ShmemVector;
class ShmemTest {
private:
managed_shared_memory *segment;
const IntAllocator *allocator_instance;
ShmemVector *test_vector;
size_t shmem_block = 10000; // Originally, I could allocate 65536 without problems
struct shm_remove {
shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
~shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
} remover;
public:
ShmemTest() {
segment = new managed_shared_memory(create_only, SHMEM_NAME.data(), shmem_block);
allocator_instance = new IntAllocator(segment->get_segment_manager());
}
void create_vector() {
test_vector = segment->construct<ShmemVector>("ShmemVector")(*allocator_instance);
}
void append(int value) {
try {
test_vector->push_back(value);
} catch (std::exception & e) { // Grow shared memory if out of memory
std::cout << e.what() << std::endl;
std::cout << "Growing the shared memory block" << std::endl;
managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
std::cout << "Done growing the shared memory block, current size: " << size();
std::cout << " max size: " << max_size() << std::endl;
test_vector->push_back(value);
std::cout << "Added value after growing shared memory block" << std::endl;
}
}
void print() {
std::cout << "ShmemVector values: ";
for (int value : *test_vector) {
std::cout << " " << value << " ";
}
std::cout << std::endl;
}
size_t max_size() {
return test_vector->max_size();
}
size_t size() {
return test_vector->size();
}
void destroy() {
segment->destroy<ShmemVector>("ShmemVector");
}
};
int main() {
ShmemTest shmem_test;
shmem_test.create_vector();
std::cout << "Max size: " << shmem_test.max_size() << std::endl;
for (int i = 0; i < 16380; ++i) {
shmem_test.append(i);
if (i > 16200) {
std::cout << "Current size: " << shmem_test.size() << " ";
}
}
std::cout << std::endl;
shmem_test.print();
shmem_test.destroy();
}
这是我得到的典型输出:
Max size: 2496
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2414 max size: 2746
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2662 max size: 2996
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2914 max size: 3246
Segmentation fault (core dumped)
解决方案
正如 oxuf 所指出的,重新映射段然后使用 find
有效。这是更新后的功能,以防万一有人遇到同样的问题:
void append(int value) {
try {
test_vector->push_back(value);
} catch (std::exception & e) { // Grow shared memory if out of memory
managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
// Re-map the shared memory segment
segment = new managed_shared_memory(open_only, SHMEM_NAME.data());
// Find the vector object in the newly mapped shared memory segment
std::pair<ShmemVector*, size_t> return_value = segment->find<ShmemVector>("ShmemVector");
test_vector = return_value.first;
// Append the value
test_vector->push_back(value);
}
}
每次段增长时,OS 可以自由地重新分配整个内存块,然后,所有指向该内存的指针都将变为无效。然后,test_vector
可能指向增长后的无效内存。尝试再次映射该段,这次使用 open_only
选项并使用 managed_shared_memory::find
到达您的 vector
.
我正在研究 boost 库的共享内存部分,为更大的项目做准备。我需要一个共享内存段,在初始化时我不一定知道它的大小,所以我的计划是增加这个段。
我的初始实现有一个 boost::interprocess::vector
存储在共享内存中。当我向向量中添加值时,如果向量的大小超过了段(抛出 bad_alloc
异常),我会增大段。这通常会工作几次,直到出现分段错误。
不确定这是否有帮助,在此实施之前,我的代码会在调用 managed_shared_memory::grow()
方法时挂起。经过一些谷歌搜索后,我发现这可能是因为该段仍然映射到主进程。当前错误发生在我将 remover
结构移出构造函数之后。现在,代码没有挂起,但它确实出现了段错误。
代码如下:
#include <iostream>
#include <exception>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
using namespace boost::interprocess;
static const std::string SHMEM_NAME = "MySharedMemorySegment";
typedef allocator<int, managed_shared_memory::segment_manager> IntAllocator;
typedef vector<int, IntAllocator> ShmemVector;
class ShmemTest {
private:
managed_shared_memory *segment;
const IntAllocator *allocator_instance;
ShmemVector *test_vector;
size_t shmem_block = 10000; // Originally, I could allocate 65536 without problems
struct shm_remove {
shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
~shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
} remover;
public:
ShmemTest() {
segment = new managed_shared_memory(create_only, SHMEM_NAME.data(), shmem_block);
allocator_instance = new IntAllocator(segment->get_segment_manager());
}
void create_vector() {
test_vector = segment->construct<ShmemVector>("ShmemVector")(*allocator_instance);
}
void append(int value) {
try {
test_vector->push_back(value);
} catch (std::exception & e) { // Grow shared memory if out of memory
std::cout << e.what() << std::endl;
std::cout << "Growing the shared memory block" << std::endl;
managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
std::cout << "Done growing the shared memory block, current size: " << size();
std::cout << " max size: " << max_size() << std::endl;
test_vector->push_back(value);
std::cout << "Added value after growing shared memory block" << std::endl;
}
}
void print() {
std::cout << "ShmemVector values: ";
for (int value : *test_vector) {
std::cout << " " << value << " ";
}
std::cout << std::endl;
}
size_t max_size() {
return test_vector->max_size();
}
size_t size() {
return test_vector->size();
}
void destroy() {
segment->destroy<ShmemVector>("ShmemVector");
}
};
int main() {
ShmemTest shmem_test;
shmem_test.create_vector();
std::cout << "Max size: " << shmem_test.max_size() << std::endl;
for (int i = 0; i < 16380; ++i) {
shmem_test.append(i);
if (i > 16200) {
std::cout << "Current size: " << shmem_test.size() << " ";
}
}
std::cout << std::endl;
shmem_test.print();
shmem_test.destroy();
}
这是我得到的典型输出:
Max size: 2496
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2414 max size: 2746
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2662 max size: 2996
Added value after growing shared memory block
boost::interprocess::bad_alloc
Growing the shared memory block
Done growing the shared memory block, current size: 2914 max size: 3246
Segmentation fault (core dumped)
解决方案
正如 oxuf 所指出的,重新映射段然后使用 find
有效。这是更新后的功能,以防万一有人遇到同样的问题:
void append(int value) {
try {
test_vector->push_back(value);
} catch (std::exception & e) { // Grow shared memory if out of memory
managed_shared_memory::grow(SHMEM_NAME.data(), 1000);
// Re-map the shared memory segment
segment = new managed_shared_memory(open_only, SHMEM_NAME.data());
// Find the vector object in the newly mapped shared memory segment
std::pair<ShmemVector*, size_t> return_value = segment->find<ShmemVector>("ShmemVector");
test_vector = return_value.first;
// Append the value
test_vector->push_back(value);
}
}
每次段增长时,OS 可以自由地重新分配整个内存块,然后,所有指向该内存的指针都将变为无效。然后,test_vector
可能指向增长后的无效内存。尝试再次映射该段,这次使用 open_only
选项并使用 managed_shared_memory::find
到达您的 vector
.