C++ Boost映射的\u文件\u源、对齐方式和页面大小

C++ Boost映射的\u文件\u源、对齐方式和页面大小,c++,boost,memory-mapped-files,C++,Boost,Memory Mapped Files,我试图在性能非常重要的上下文中解析一些大小高达几百兆字节的文本文件,所以我使用boost mapped_file_source。解析器希望源代码以空字节终止,因此我想检查文件大小是否是页面大小的精确倍数(如果是,请使用较慢的非内存映射方法)。我想我可以这样做: if (mf.size() & (mf.alignment() - 1)) 但在一个大小为20480的测试文件上,对齐为65536(在Windows7上为64位),程序正在崩溃。我认为现在的情况是页面大小实际上小于对齐方式,所以

我试图在性能非常重要的上下文中解析一些大小高达几百兆字节的文本文件,所以我使用boost mapped_file_source。解析器希望源代码以空字节终止,因此我想检查文件大小是否是页面大小的精确倍数(如果是,请使用较慢的非内存映射方法)。我想我可以这样做:

if (mf.size() & (mf.alignment() - 1))
但在一个大小为20480的测试文件上,对齐为65536(在Windows7上为64位),程序正在崩溃。我认为现在的情况是页面大小实际上小于对齐方式,所以我的测试不起作用


如何获取页面大小?还是我应该做些别的事?(我需要针对Windows和Linux的解决方案,如果必要,我愿意编写特定于系统的代码,但如果可能的话,我更喜欢可移植代码。)

最简单的方法是修复解析器,将输入的末尾考虑在内(真的不太离谱)

接下来:一个大警告。依赖于映射中的尾随字节(如果有)为零是未定义的

因此,只需使用size+1映射文件,并确定地添加NUL终止符即可。我认为这不值得深入研究特定于平台/未定义的行为

事实上,我刚刚了解了
boost::iostreams::mapped_file_base::mapmode::priv
,它非常适合您的需要:

可以写入以专用访问权限打开的文件,但更改不会影响基础文件[]

这里有一个简单的片段:

#include <boost/iostreams/device/mapped_file.hpp>
#include <fstream>
#include <iostream>

namespace io = boost::iostreams;

int main() {
    // of course, prefer `stat(1)` or `boost::filesystem::file_size()`, but for exposition:
    std::streamsize const length = std::distance(std::istreambuf_iterator<char>(std::ifstream("main.cpp").rdbuf()), {});

    io::mapped_file mf("main.cpp", io::mapped_file_base::mapmode::priv, length+1);

    *(mf.end()-1) = '\0'; // voilà, null termination done, safely, quickly and reliably

    std::cout << length << "\n";
    std::cout << mf.size() << "\n";
}


可能会杀死兔子或使进程崩溃。

什么是“解析器希望源以空字节终止”?由于您立即执行“因此,我想检查文件大小是否是页面大小的精确倍数”。我不明白。@sehe空字节不包含在文件数据本身中。如果文件大小不是页面大小的精确倍数,则最终页面的其余部分将显示为空字节,满足要求,但如果文件大小是精确倍数,则解析器将尝试读取最后页面的末尾,并触发分段错误。我没有回答您的问题,因为这是一个经典问题。实际上,您只想知道如何NUL终止只读文件映射。还有更好的方法,我的回答就是这些。
mf.data()[length] = '\0'; // voilà, null termination done, safely, quickly and reliably
*(mf.begin()+length) = 0; // etc.