简体   繁体   English

circular_buffer 和 managed_mapped_file 分段错误

[英]circular_buffer and managed_mapped_file segmentation fault

I am using boost 1.73.0, and am trying to use circular_buffer together with manage_mapped_file to store strings in a circular buffer persisted on disk.我正在使用 boost 1.73.0,并尝试将循环缓冲区与 manage_mapped_file 一起使用以将字符串存储在磁盘上持久的循环缓冲区中。

I do the following to create/open the circular_buffer:我执行以下操作来创建/打开循环缓冲区:

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());

This works well and I can put strings in the circular_buffer like this:这很好用,我可以像这样将字符串放在 circular_buffer 中:

for(int idx = 0 ; idx < 15; idx++) {
    std::string v = "mystring1-" + std::to_string(idx);
    instance->push_back(v);
}

Looking at the raw file (even though it is binary) I dosee the strings inthere, so it seems like the circular_buffer was indeed persisted.查看原始文件(即使它是二进制文件),我确实看到了其中的字符串,所以看起来 circle_buffer 确实被保留了。

But, if I try to load the circular_buffer in another process as shown in the first code snippet and read the first element like this:但是,如果我尝试在另一个进程中加载 circular_buffer,如第一个代码片段所示,并像这样读取第一个元素:

instance->front()

I get a segmentation fault.我得到一个分段错误。 I know that in the end I will need sychronization around memory access, but this should not be the problem in the example above as only one process is accessing the file a any given time.我知道最后我需要围绕 memory 访问进行同步,但这不应该是上面示例中的问题,因为在任何给定时间只有一个进程正在访问文件。

The funny thing is that if I substitute std::string with char in the allocator I do not get the segmentation fault.有趣的是,如果我在分配器中用 char 替换 std::string,我不会得到分段错误。 What am I doing wrong?我究竟做错了什么?

Rgds Klaus 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());

You allocate the string objects in shared memory.您在共享 memory 中分配string对象。 However, string itself allocates, and you never told it to use the shared-memory allocator.但是, string本身会分配,而您从未告诉它使用共享内存分配器。

The reason you may be seeing short strings inside the data is because of SSO您可能会在数据中看到字符串的原因是SSO

Fixed Version固定版本

Live On Coliru住在科利鲁

#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()));
    }
}

On the second run prints:在第二次运行打印:

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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM