简体   繁体   中英

Read access violation for memory mapped vector in debug mode

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:

在此处输入图片说明

Here the point where the exception happens:

在此处输入图片说明

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

在此处输入图片说明

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:

在此处输入图片说明

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

在此处输入图片说明

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!

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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