调试模式下内存映射向量的读取访问冲突

Read access violation for memory mapped vector in debug mode

在尝试使用 boost::interprocess 在内存映射文件中存储 std::vector 时,当我尝试推回加载的向量时出现异常 Exception thrown: read access violation.,但是仅在调试模式下

这个最小的示例代码(由@sehe 编写)是从 中检索到的,它在调试模式下在 MSVC14 上崩溃 并且 执行了不止一次:

#include <boost/interprocess/managed_mapped_file.hpp>

namespace bi = boost::interprocess;

int main() {
    std::string vecFile = "vector.dat";
    bi::managed_mapped_file file_vec(bi::open_or_create,vecFile.c_str(), 1000);

    typedef bi::allocator<int, bi::managed_mapped_file::segment_manager> int_alloc;
    typedef std::vector<int, int_alloc>  MyVec;

    MyVec * vecptr = file_vec.find_or_construct<MyVec>("myvector")(file_vec.get_segment_manager());

    vecptr->push_back(rand());
}

编辑:

这是 Visual Studio 错误消息:

这里是异常发生的地方:

这是调用堆栈(点击图片放大):

作为脑电波,disable MSVC debug iterators

我不确定如何(因为迭代器不是持久化的?)但是迭代器调试可能会以某种方式在 std::vector 的内存布局中添加原始指针 - 违反了关于分配器使用的标准库假设。

测试结果

为此目的在 azure 上创建一个 VM,使用以下稍微修改的代码进行测试以更好地理解崩溃原因:

#include <boost/interprocess/managed_mapped_file.hpp>
#include <iostream>

namespace bi = boost::interprocess;

int main() {
    std::string vecFile = "vector.dat";
    //std::remove(vecFile.c_str());
    std::cout << __LINE__ << "\n";
    {
        bi::managed_mapped_file file_vec(bi::open_or_create, vecFile.c_str(), 100000);

        typedef bi::allocator<int, bi::managed_mapped_file::segment_manager> int_alloc;
        typedef std::vector<int, int_alloc>  MyVec;

        MyVec * vecptr = file_vec.find_or_construct<MyVec>("myvector")(file_vec.get_segment_manager());

        vecptr->push_back(rand());
        std::cout << "size: " << vecptr->size() << "\n";
    }
    std::cout << __LINE__ << "\n";
    {
        bi::managed_mapped_file file_vec(bi::open_or_create, vecFile.c_str(), 100000);

        typedef bi::allocator<int, bi::managed_mapped_file::segment_manager> int_alloc;
        typedef std::vector<int, int_alloc>  MyVec;

        MyVec * vecptr = file_vec.find_or_construct<MyVec>("myvector")(file_vec.get_segment_manager());

        vecptr->push_back(rand());
        std::cout << "size: " << vecptr->size() << "\n";
    }
    std::cout << __LINE__ << "\n";
}

重现问题。首先运行:

后续 运行(std::remove 行的注释如图所示):

变通方案演示

放后

#define _ITERATOR_DEBUG_LEVEL 0

在最顶部 并删除 vector.dat 文件,因为更改改变了二进制布局:

Note: in your actual project you may require putting that #define in multiple translation units (especially consider stdafx.cpp). It's probably much better to include it in the project property sheets so it applies to all (future) translation units!