无法从 Boost::mapped_file 读取:数据缓冲区为 NULL

Cannot read from Boost::mapped_file: Data buffer is NULL

我正在尝试以块的形式从映射文件中读取(因此 buffer_sizefile_offset 参数)但缓冲区始终是 NULL。文件打开成功。我的代码如下:

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

namespace filesystem = boost::filesystem;

using std::ios;
using std::ifstream;

char *read_mapped_bytes(const char *file_path, boost::iostreams::mapped_file mapped_file,
                        unsigned long long int buffer_size, unsigned long long int file_offset) {
    const filesystem::path memory_dump_file{file_path};
    mapped_file.open(memory_dump_file, boost::iostreams::mapped_file::readonly, buffer_size,
                     static_cast<boost::iostreams::stream_offset>(file_offset));
    if (mapped_file.is_open()) {
        auto read_buffer = mapped_file.data();
        if (read_buffer == nullptr) {
            printf("The mapped file buffer was NULL");
            exit(-1);
        }
        return read_buffer;
    } else {
        printf("Failed to open mapped file");
        exit(-1);
    }
}

int main(int argc, char *argv[]) {
    boost::iostreams::mapped_file mapped_file;
    auto buffer = read_mapped_bytes((const char *) "/mnt/d/Cpp/MyProject/myFile.bin", mapped_file,
                                    (unsigned long long int) 1000, (unsigned long long int) 0);

    exit(EXIT_SUCCESS);
}

注意文件路径正确,否则会导致异常:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::ios_base::failure[abi:cxx11]> >'
  what():  failed opening file: No such file or directory: iostream error

代码已在 Ubuntu 18.04.01 LTS 上 运行 使用 WSL (Windows Subsystem for Linux)。

代码执行的strace(strace -ff -o test.txt ./BoostTesting)如下:

execve("./BoostTesting", ["./BoostTesting"], 0x7fffc2c75168 /* 17 vars */) = 0
brk(NULL)                               = 0x7fffc5980000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=48784, ...}) = 0
mmap(NULL, 48784, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4759dab000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.65.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]00[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=105032, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4759da0000
mmap(NULL, 2200080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f47597e0000
mprotect(0x7f47597f8000, 2097152, PROT_NONE) = 0
mmap(0x7f47599f8000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7f47599f8000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]00[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=18544, ...}) = 0
mmap(NULL, 2113856, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f47595d0000
mprotect(0x7f47595d4000, 2093056, PROT_NONE) = 0
mmap(0x7f47597d3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f47597d3000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]03[=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=1594832, ...}) = 0
mmap(NULL, 3702816, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4759240000
mprotect(0x7f47593b9000, 2097152, PROT_NONE) = 0
mmap(0x7f47595b9000, 49152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x179000) = 0x7f47595b9000
mmap(0x7f47595c5000, 12320, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f47595c5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]0*[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=96616, ...}) = 0
mmap(NULL, 2192432, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4759020000
mprotect(0x7f4759037000, 2093056, PROT_NONE) = 0
mmap(0x7f4759236000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7f4759236000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]0[=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4758c20000
mprotect(0x7f4758e07000, 2097152, PROT_NONE) = 0
mmap(0x7f4759007000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f4759007000
mmap(0x7f475900d000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f475900d000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]0[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=116960, ...}) = 0
mmap(NULL, 2212016, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4758a00000
mprotect(0x7f4758a1c000, 2093056, PROT_NONE) = 0
mmap(0x7f4758c1b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b000) = 0x7f4758c1b000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libbz2.so.1.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]`[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=66800, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4759d90000
mmap(NULL, 2161864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f47587f0000
mprotect(0x7f47587ff000, 2093056, PROT_NONE) = 0
mmap(0x7f47589fe000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe000) = 0x7f47589fe000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]00b[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=144976, ...}) = 0
mmap(NULL, 2221184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f47585d0000
mprotect(0x7f47585ea000, 2093056, PROT_NONE) = 0
mmap(0x7f47587e9000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19000) = 0x7f47587e9000
mmap(0x7f47587eb000, 13440, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f47587eb000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]>[=13=][=13=][=13=][=13=]02[=13=][=13=][=13=][=13=][=13=][=13=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=1700792, ...}) = 0
mmap(NULL, 3789144, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f4758230000
mprotect(0x7f47583cd000, 2093056, PROT_NONE) = 0
mmap(0x7f47585cc000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19c000) = 0x7f47585cc000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4759d80000
arch_prctl(ARCH_SET_FS, 0x7f4759d811c0) = 0
mprotect(0x7f4759007000, 16384, PROT_READ) = 0
mprotect(0x7f47585cc000, 4096, PROT_READ) = 0
mprotect(0x7f47587e9000, 4096, PROT_READ) = 0
mprotect(0x7f47589fe000, 4096, PROT_READ) = 0
mprotect(0x7f4758c1b000, 4096, PROT_READ) = 0
mprotect(0x7f4759236000, 4096, PROT_READ) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4759d70000
mprotect(0x7f47595b9000, 40960, PROT_READ) = 0
mprotect(0x7f47597d3000, 4096, PROT_READ) = 0
mprotect(0x7f47599f8000, 4096, PROT_READ) = 0
mprotect(0x7f475a008000, 4096, PROT_READ) = 0
mprotect(0x7f4759c27000, 4096, PROT_READ) = 0
munmap(0x7f4759dab000, 48784)           = 0
set_tid_address(0x7f4759d81490)         = 1491
set_robust_list(0x7f4759d814a0, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7f47585d5cb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f47585e2890}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7f47585d5d50, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f47585e2890}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=8192*1024}) = 0
brk(NULL)                               = 0x7fffc5980000
brk(0x7fffc59a1000)                     = 0x7fffc59a1000
futex(0x7f47595c607c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f47595c6088, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/mnt/d/Cpp/MyProject/myFile.bin", O_RDONLY) = 3
mmap(NULL, 1000, PROT_READ, MAP_SHARED, 3, 0) = 0x7f4759db6000
fstat(1, {st_mode=S_IFCHR|0660, st_rdev=makedev(4, 1), ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, "The mapped file buffer was NULL", 31) = 31
exit_group(-1)                          = ?
+++ exited with 255 +++

请注意,为 Windows 编译时会出现同样的问题,所以这很可能是我的代码或 Boost.

中的错误

原来我传递了错误的参数。此外,偏移量必须是 page size 的倍数。这是独立于平台的示例源代码,演示了使用 mapped_file:

对文件进行分块迭代
#include <boost/iostreams/device/mapped_file.hpp>
#include <iostream>
#include <boost/filesystem.hpp>

#ifdef _WIN32

#include <sysinfoapi.h>

#endif

namespace filesystem = boost::filesystem;
namespace io_streams = boost::iostreams;

using std::ios;
using std::ifstream;

unsigned long long int get_page_size() {
#ifdef _WIN32
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    return (unsigned long long int) sysInfo.dwPageSize;
#else
    return (unsigned long long int) sysconf(_SC_PAGE_SIZE);
#endif
}

unsigned long long int get_file_size(const char *file_path) {
    filesystem::path file{file_path};
    auto generic_path = file.generic_path();
    return filesystem::file_size(generic_path);
}

std::vector<char> read_bytes(const char *file_path,
                             unsigned long long int offset,
                             unsigned long long int length) {
    io_streams::mapped_file_params parameters;
    parameters.path = file_path;
    parameters.length = static_cast<size_t>(length);
    parameters.flags = io_streams::mapped_file::mapmode::readonly;
    parameters.offset = static_cast<boost::iostreams::stream_offset>(offset);

    boost::iostreams::mapped_file_source file;

    file.open(parameters);

    if (file.is_open()) {
        auto buffer = file.data();
        std::vector<char> vector_buffer;
        for (auto buffer_index = 0; buffer_index < length; buffer_index++) {
            auto byte = buffer[buffer_index];
            vector_buffer.push_back(byte);
        }

        return vector_buffer;
    } else {
        printf("Failed to open file\n");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[]) {
#ifdef _WIN32
    auto file_path = (const char *) R"(D:\Cpp\BoostTesting\test.bin)";
#else
    auto file_path = (const char *) "/mnt/d/Cpp/BoostTesting/test.bin";
#endif

    unsigned long long int offset = 0;
    unsigned long long int page_size = get_page_size();
    auto buffer_size = page_size;
    auto total_length = get_file_size(file_path);

    while (offset < total_length) {
        auto remaining_bytes = total_length - offset;
        if (buffer_size > remaining_bytes) {
            buffer_size = remaining_bytes;
        }

        auto buffer = read_bytes(file_path, offset, buffer_size);
        for (auto byte : buffer) {
            printf("%i ", byte);
        }

        offset += buffer_size;
    }

    return EXIT_SUCCESS;
}