【问题标题】:C++ Can memory mapped files (boost::interprocess) move during program execution?C++ 内存映射文件(boost::interprocess)可以在程序执行期间移动吗?
【发布时间】:2014-01-29 22:33:30
【问题描述】:

我读了一个这样的 5GB 大文件:

类的数据成员:

char* raw_bytes;
unsigned long long raw_bytes_size;
file_mapping* fm;
mapped_region* region;
unsigned long long file_offset;
MyClass co; (not including details of this as irrelevant)

构造函数:

FileReader::FileReader(const char* FilePath, unsigned long long file_offset_pos){
    fm = new file_mapping(FilePath, boost::interprocess::read_only);
    region = new mapped_region(*fm, boost::interprocess::read_only);
    raw_bytes_size = region->get_size();
    raw_bytes = static_cast<char*>(region->get_address());
    file_offset = file_offset_pos;
    Iterate(raw_bytes, raw_bytes_size);
}

遍历映射文件:

void FileReader::Iterate(char* rawbytes, unsigned long long size){
    unsigned long long i = file_offset;
    while(i < size){
        std::vector<char> order_bytes = co->getBytes(rawbytes, i);
    }
}

处理每条消息的不同类(84 字节长):

std::vector<char> B::getBytes(char* rawbytes, unsigned long long& pos){
    std::vector<char> bytes;

    int message_length = 84;
    unsigned long long last_pos = pos + message_length;

    bytes.reserve(message_length);
    while (pos < last_pos){                    
        bytes.push_back(rawbytes[pos]);   //The exception occurs here
        pos++;
    }

    return bytes;
}

现在,如果您仔细查看此代码 - 它可以正常工作。但是,在说 500MB 或 1GB 之后,我突然在while (pos &lt; last_pos) 处收到一个错误。当抛出异常并且 Visual Studio 允许我在 VS 实例中进行调试时,当我将鼠标悬停在变量 last_pos 和 rawbytes VS 说它们无法读取时,但 pos 的 memory 可以????就好像底层内存映射文件在处理过程中改变了位置。

注意:我绝对没有用完 RAM。有什么建议吗?

错误信息是:

MyProgram.exe 中 0x000000013F86A05C 处未处理的异常: 0xC0000005:访问冲突读取位置0x0000000527533000。

  • 当我将鼠标悬停在rawbytes 上时,它会显示值:0x0000000000000000
  • pos 的值为 3825504
  • 文件的原始大小,raw_bytes_size 最初是:2554061585

调用栈停在B::getBytes()

更新:如果我运行几次,每次我得到异常pos(读取下一条消息的位置标记)的值都是不同的......所以它不是因为我已经超出了文件(加上pos 也比文件的大小每次都小得多)。

【问题讨论】:

  • 尝试捕捉异常?这可能会有所帮助
  • 我希望我能对你的 cmets 投反对票,@piotruś。无论如何,验证您的指针是否被炸毁可能会有所帮助,也许可以通过保存其初始值并使用assert 对其进行测试。 VS 对“当前值”翻转并不总是有帮助。虽然不一定是问题,但您似乎确实存在潜在的缓冲区溢出:调用getBytes 的循环不考虑将检查超过当前位置的字节数(换句话说,可以允许getBytes读取缓冲区的末尾)。
  • @paddy 对此感到抱歉,您必须喜欢做其他事情,也许可以转到我的个人资料并单击我的兴趣描述中的可点击项目
  • @paddy 如果我在遇到问题后以调试而不是发布模式运行,它会改变什么吗?
  • 您是否正在为 64 位架构进行编译? (我相信一些 32 位程序可以使用 PAE 解决 >2GiB 的问题?)

标签: c++ boost memory-mapped-files


【解决方案1】:

不,mmap 不会自发移动(但它不需要跨重映射在同一个地址)。

试试

if (size>=84) 
{
     while(i < (size-84))
     {
         std::vector<char> order_bytes = co->getBytes(rawbytes, i);
     }
}

考虑到映射时文件不是 84 的倍数的情况(并非不可能?)。

【讨论】:

  • 但是pos(本质上是一个位置标记)比文件的大小要小很多。
  • 我认为您需要检查该假设。如果这不是问题,那么您有修改指针的“简单”内存损坏/UB...(可能是文件在打开后被重写/截断?)
猜你喜欢
  • 2013-11-29
  • 2020-10-19
  • 2012-11-26
  • 2016-01-08
  • 2011-02-01
  • 2012-09-06
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多