内存映射文件问题
Memory mapped file problems
在我的 C++ 代码中,我需要将大量数据写入文件,我想使用 boost 映射文件 而不是使用普通文件。只有当我将所有数据写入内存后,我才想一次性将映射文件转储到磁盘。
我在 Windows Server 2008 R2 和 boost 1.58 上使用 Visual Studio 2010。
我从未使用过映射文件,所以我尝试编译 boost 文档中的示例
#include <iostream>
#include <fstream>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
int main(int argc, char** argv)
{
using namespace boost::interprocess;
const char* fileName = "C:\logAcq\test.bin";
const std::size_t fileSize = 10000;
std::cout << "create file" << std::endl;
try
{
file_mapping::remove(fileName);
std::filebuf fbuf;
fbuf.open(fileName, std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
std::cout << "set size" << std::endl;
fbuf.pubseekoff(fileSize-1, std::ios_base::beg);
fbuf.sputc(0);
std::cout << "remove on exit" << std::endl;
struct file_remove
{
file_remove(const char* fileName)
:fileName_(fileName) {}
~file_remove(){ file_mapping::remove(fileName_); }
const char *fileName_;
}remover(fileName);
std::cout << "create file mapping" << std::endl;
file_mapping m_file(fileName, read_write);
std::cout << "map the whole file" << std::endl;
mapped_region region(m_file, read_write);
std::cout << "get the address" << std::endl;
void* addr = region.get_address();
std::size_t size = region.get_size();
std::cout << "write all memory to 1" << std::endl;
memset(addr, 1, size);
}
catch (interprocess_exception &ex)
{
fprintf(stderr, "Exception %s\n", ex.what());
fflush(stderr);
system("PAUSE");
return 0;
}
system("PAUSE");
return 0;
}
但我遇到了异常
异常文件的体积已被外部更改,因此打开的文件不再有效。
当我创建区域时
"mapped_region region(m_file, read_write)"
感谢任何帮助。
谢谢
Exception The volume for a file has been externally altered so that the opened file is no longer valid.
强烈建议该文件在映射时被另一个程序更改。并且错误消息表明更改碰巧以不允许的方式影响大小。
避免其他程序写入文件,或采取适当的同步和共享预防措施(例如,不要更改大小,或仅增长等)
更新
您添加的 SSCCE 确认您在映射时保持文件打开:
您需要在映射文件之前关闭 fbuf
。此外,您需要先删除映射,然后才能删除它。
工作样本:
#include <iostream>
#include <fstream>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
int main() {
using namespace boost::interprocess;
const char *fileName = "test.bin";
const std::size_t fileSize = 10000;
std::cout << "create file " << fileName << std::endl;
try {
file_mapping::remove(fileName);
{
std::filebuf fbuf;
fbuf.open(fileName, std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
std::cout << "set size" << std::endl;
fbuf.pubseekoff(fileSize - 1, std::ios_base::beg);
fbuf.sputc(0);
}
std::cout << "remove on exit" << std::endl;
struct file_remove {
file_remove(const char *fileName) : fileName_(fileName) {}
~file_remove() { file_mapping::remove(fileName_); }
const char *fileName_;
} remover(fileName);
{
std::cout << "create file mapping" << std::endl;
file_mapping m_file(fileName, read_write);
std::cout << "map the whole file" << std::endl;
mapped_region region(m_file, read_write);
std::cout << "get the address" << std::endl;
void *addr = region.get_address();
std::size_t size = region.get_size();
std::cout << "write all memory to 1" << std::endl;
memset(addr, 1, size);
}
} catch (interprocess_exception &ex) {
fprintf(stderr, "Exception %s\n", ex.what());
fflush(stderr);
}
}
在我的 C++ 代码中,我需要将大量数据写入文件,我想使用 boost 映射文件 而不是使用普通文件。只有当我将所有数据写入内存后,我才想一次性将映射文件转储到磁盘。
我在 Windows Server 2008 R2 和 boost 1.58 上使用 Visual Studio 2010。
我从未使用过映射文件,所以我尝试编译 boost 文档中的示例
#include <iostream>
#include <fstream>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
int main(int argc, char** argv)
{
using namespace boost::interprocess;
const char* fileName = "C:\logAcq\test.bin";
const std::size_t fileSize = 10000;
std::cout << "create file" << std::endl;
try
{
file_mapping::remove(fileName);
std::filebuf fbuf;
fbuf.open(fileName, std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
std::cout << "set size" << std::endl;
fbuf.pubseekoff(fileSize-1, std::ios_base::beg);
fbuf.sputc(0);
std::cout << "remove on exit" << std::endl;
struct file_remove
{
file_remove(const char* fileName)
:fileName_(fileName) {}
~file_remove(){ file_mapping::remove(fileName_); }
const char *fileName_;
}remover(fileName);
std::cout << "create file mapping" << std::endl;
file_mapping m_file(fileName, read_write);
std::cout << "map the whole file" << std::endl;
mapped_region region(m_file, read_write);
std::cout << "get the address" << std::endl;
void* addr = region.get_address();
std::size_t size = region.get_size();
std::cout << "write all memory to 1" << std::endl;
memset(addr, 1, size);
}
catch (interprocess_exception &ex)
{
fprintf(stderr, "Exception %s\n", ex.what());
fflush(stderr);
system("PAUSE");
return 0;
}
system("PAUSE");
return 0;
}
但我遇到了异常
异常文件的体积已被外部更改,因此打开的文件不再有效。
当我创建区域时
"mapped_region region(m_file, read_write)"
感谢任何帮助。
谢谢
Exception The volume for a file has been externally altered so that the opened file is no longer valid.
强烈建议该文件在映射时被另一个程序更改。并且错误消息表明更改碰巧以不允许的方式影响大小。
避免其他程序写入文件,或采取适当的同步和共享预防措施(例如,不要更改大小,或仅增长等)
更新
您添加的 SSCCE 确认您在映射时保持文件打开:
您需要在映射文件之前关闭 fbuf
。此外,您需要先删除映射,然后才能删除它。
工作样本:
#include <iostream>
#include <fstream>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
int main() {
using namespace boost::interprocess;
const char *fileName = "test.bin";
const std::size_t fileSize = 10000;
std::cout << "create file " << fileName << std::endl;
try {
file_mapping::remove(fileName);
{
std::filebuf fbuf;
fbuf.open(fileName, std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
std::cout << "set size" << std::endl;
fbuf.pubseekoff(fileSize - 1, std::ios_base::beg);
fbuf.sputc(0);
}
std::cout << "remove on exit" << std::endl;
struct file_remove {
file_remove(const char *fileName) : fileName_(fileName) {}
~file_remove() { file_mapping::remove(fileName_); }
const char *fileName_;
} remover(fileName);
{
std::cout << "create file mapping" << std::endl;
file_mapping m_file(fileName, read_write);
std::cout << "map the whole file" << std::endl;
mapped_region region(m_file, read_write);
std::cout << "get the address" << std::endl;
void *addr = region.get_address();
std::size_t size = region.get_size();
std::cout << "write all memory to 1" << std::endl;
memset(addr, 1, size);
}
} catch (interprocess_exception &ex) {
fprintf(stderr, "Exception %s\n", ex.what());
fflush(stderr);
}
}