Read access violation for memory mapped vector in

2019-04-17 06:26发布

While attempting to use boost::interprocess for storing a std::vector in a memory mapped file, I am getting the exception Exception thrown: read access violation. when I try to push back on a loaded vector, but only in debug mode.

This minimal example code (written by @sehe) is retrieved from https://stackoverflow.com/a/29602884/2741329, and it crashes on MSVC14 in debug mode and executed more than once:

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

EDIT:

This is the Visual Studio error message:

enter image description here

Here the point where the exception happens:

enter image description here

This is the call stack (click on the pic to enlarge it):

enter image description here

1条回答
劫难
2楼-- · 2019-04-17 06:34

As a brainwave, disable MSVC debug iterators.

I'm not sure how (because iterators aren't persisted?) but somehow iterator debugging might add raw pointers inside the memory layout of the std::vector - violating standard library assumptions about allocator use.

Test Results

Creating a VM on azure just for the purpose, tested with the following slightly modified code to better understand the crash reasons:

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

Reproduces the issue. First run:

enter image description here

Subsequent run (with the std::remove line commented as shown):

enter image description here

WORKAROUND DEMO

After putting

#define _ITERATOR_DEBUG_LEVEL 0

at the very top AND REMOVING THE vector.dat file because the change alters binary layout:

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!

enter image description here

查看更多
登录 后发表回答