std::filesystem:file_size 给我一个不连贯的值

std::filesystem:file_size send me an incoherent value

为了在我的代码中读取一个文件,我使用std::filesystem::file_size(https://en.cppreference.com/w/cpp/filesystem/file_size)来获取他的大小。我使用此代码:

template <typename TYPE>
inline void read_binary_file(const fs::path filename, std::vector<TYPE>& result) 
{ 
  std::ifstream file(filename, std::ios::in | std::ios::binary); 
  __ERR_READFILE01__ // file cannot be open 
  SPDLOG_DEBUG("Reading {}", filename.u8string()); 
 
  size_t filesize; 
  try
  { 
    filesize = fs::file_size(filename); 
  } 
  catch(fs::filesystem_error& e) 
  { 
    std::cout << e.what() << '\n'; abort(); 
  } 
  assert(filesize%sizeof(TYPE) == 0); 
  SPDLOG_DEBUG("size of file {}", filesize); 
  SPDLOG_DEBUG("size of {}", static_cast<std::uintmax_t>(-1)); 
  SPDLOG_DEBUG("size of type {}", sizeof(TYPE)); 
  SPDLOG_DEBUG("size of the reading vector {}", filesize/sizeof(TYPE));  
  result.resize(filesize/sizeof(TYPE)); 
  file.read(reinterpret_cast<char*>(result.data()), filesize); 
  file.close(); 
}

这适用于我需要读取的大部分文件,但对于一个文件 (~3 gigas),我有一个奇怪的问题:

[07/12/2020 11:52:42][debug] size of file 18446744072617361848 
[07/12/2020 11:52:42][debug] size of 18446744073709551615 
[07/12/2020 11:52:42][debug] size of type 4 
[07/12/2020 11:52:42][debug] size of the reading vector 4611686018154340462

在文档中,我可以阅读 The non-throwing overload returns static_cast<std::uintmax_t>(-1) on errors. 。但是值18446744072617361848和static_cast<std::uintmax_t>(-1)不一样,所以我迷路了....

我的编译器是mingw32 :

mingw32-make.exe --version 
GNU Make 4.3 Built for Windows32 Copyright (C) 1988-2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

我在 linux (gcc) 上没有问题。

有一个错误将在最新版本的 MinGW 中得到纠正。比较:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95749

但事件,应该取代

  size_t filesize; 

来自

std::uintmax_t filesize; 

根据函数的签名:

std::uintmax_t file_size( const std::filesystem::path& p );

fs::file_size(filename);returns一个std::uintmax_t。这可能是一个 64 位整数。您将其分配给一个 size_t ,它可能(并且可能会给出您的错误)一个 32 位整数。

只需使用 uintmax_t:

uintmax_t filesize;

这可能是 MinGW32 的一个错误。你刚刚得到的size是3202777528的signed extension,这个值你可以自己查:

uint32_t real_file_size = 3202777528u; // roughly 3GB as you said
auto value_you_see = (uint64_t)(int32_t)real_file_size;

我的猜测是 MinGW32 在内部使用 ssize_t,这是 32 位环境中 int32_t 的别名。也许你应该改用 MinGW64。

正如 Florent 所说,它似乎是 bug. gcc 10.2 on windows 使用 _wstat 的 32 位函数。即将在 windows.

的 gcc 10.3 版本中进行更正