调试模式下内存映射向量的读取访问冲突
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!
在尝试使用 boost::interprocess
在内存映射文件中存储 std::vector
时,当我尝试推回加载的向量时出现异常 Exception thrown: read access violation.
,但是仅在调试模式下。
这个最小的示例代码(由@sehe 编写)是从
#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 considerstdafx.cpp
). It's probably much better to include it in the project property sheets so it applies to all (future) translation units!