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!