c++ - circular_buffer 和 managed_mapped_file 分段错误
问题描述
我正在使用 boost 1.73.0,并尝试将循环缓冲区与 manage_mapped_file 一起使用以将字符串存储在磁盘上持久的循环缓冲区中。
我执行以下操作来创建/打开循环缓冲区:
boost::interprocess::managed_mapped_file mmf(boost::interprocess::open_or_create, "./circ_buffer.bin", 10u << 10);
typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_mapped_file::segment_manager> string_allocator;
typedef boost::circular_buffer<std::string, string_allocator> circ_buf;
circ_buf* instance = mmf.find_or_construct<circ_buf>("some_name")(10, mmf.get_segment_manager());
这很好用,我可以像这样将字符串放在 circular_buffer 中:
for(int idx = 0 ; idx < 15; idx++) {
std::string v = "mystring1-" + std::to_string(idx);
instance->push_back(v);
}
查看原始文件(即使它是二进制文件),我确实看到了其中的字符串,所以看起来 circle_buffer 确实被保留了。
但是,如果我尝试在另一个进程中加载 circular_buffer,如第一个代码片段所示,并像这样读取第一个元素:
instance->front()
我得到一个分段错误。我知道最后我需要围绕内存访问进行同步,但这不应该是上面示例中的问题,因为在任何给定时间只有一个进程正在访问文件。
有趣的是,如果我在分配器中用 char 替换 std::string,我不会得到分段错误。我究竟做错了什么?
Rgds克劳斯
解决方案
boost::interprocess::managed_mapped_file mmf(boost::interprocess::open_or_create, "./circ_buffer.bin", 10u << 10);
typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_mapped_file::segment_manager> string_allocator;
typedef boost::circular_buffer<std::string, string_allocator> circ_buf;
circ_buf* instance = mmf.find_or_construct<circ_buf>("some_name")(10, mmf.get_segment_manager());
string
您在共享内存中分配对象。但是,string
它自己进行分配,而您从未告诉它使用共享内存分配器。
您可能会在数据中看到短字符串的原因是SSO
固定版本
#include <boost/circular_buffer.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
#include <iomanip>
namespace bip = boost::interprocess;
namespace Shared {
using Mem = bip::managed_mapped_file;
using Segment = Mem::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Segment>;
template <typename T> using Buffer = boost::circular_buffer<T, Alloc<T> >;
using String = bip::basic_string<char, std::char_traits<char>, Alloc<char> >;
using StringBuf = Buffer<String>;
}
int main() {
using namespace Shared;
Mem mmf(bip::open_or_create, "./circ_buffer.bin", 10U << 10);
auto& buf = *mmf.find_or_construct<StringBuf>("some_name")(10, mmf.get_segment_manager());
for (auto& s : buf) {
std::cout << "Existing " << std::quoted(std::string_view(s)) << "\n";
}
for (char const* init : {"foo", "bar",
"some pretty long string to make sure we don't fall into SSO territory"
"some pretty long string to make sure we don't fall into SSO territory"
"some pretty long string to make sure we don't fall into SSO territory"
"some pretty long string to make sure we don't fall into SSO territory"
})
{
buf.push_back(String(init, mmf.get_segment_manager()));
}
}
在第二次运行打印:
Existing "foo"
Existing "bar"
Existing "some pretty long string to make sure we don't fall into SSO territorysome pretty long string to make sure we don't fall into SSO territorysome pretty long string to make sure we don't fall into SSO territorysome pretty long string to make sure we don't fall into SSO territory"
推荐阅读
- r - 从数据中去除时间部分并使用 R 计算连续行之间的时间差
- google-apps-script - GAS 类电子表格应用程序:追加行和合并单元格
- python-3.x - 重新使用华为调制解调器 E3372h 的令牌
- java - Java 错误 1876 --- [主要] osbdLoggingFailureAnalysisReporter:
- jekyll - 从 Jekyll 帖子创建图像
- c# - 自定义错误页面未显示在网站上,但在 Visual Studio 中运行时会显示
- python - 如何修复 ValueError:无法将字符串转换为浮点数
- bash - Bash函数没有返回预期的输出
- excel-formula - Excel公式如果那么
- php - 强制 Apache 为 HEAD 请求返回 Content Length 0