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

时间:2018-07-14 02:39:43

标签: c++ visual-studio-2015 memory-mapped-files boost-interprocess

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

此最小示例代码(由@sehe编写)是从https://stackoverflow.com/a/29602884/2741329中检索到的,它在调试模式上的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错误消息:

enter image description here

在这里发生异常:

enter image description here

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

enter image description here

1 个答案:

答案 0 :(得分:1)

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";
}

重现该问题。第一次运行:

enter image description here

后续运行(带有std::remove行的注释,如下所示):

enter image description here

WORKAROUND DEMO

放置后

#define _ITERATOR_DEBUG_LEVEL 0

位于最上方的并删除vector.dat文件,因为更改会更改二进制布局

  

注意:在您的实际项目中,您可能需要将#define放在多个翻译单元中(尤其要考虑stdafx.cpp)。最好将其包含在项目属性表中,以便将其应用于所有(将来的)翻译单元!

enter image description here