std::filesystem:file_size отправляет мне некогерентное значение

#c #mingw #std-filesystem

#c #mingw #std-файловая система

Вопрос:

Чтобы прочитать файл в моем коде, я использую 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>amp; 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_erroramp; 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 гигабайта) у меня странная проблема :

 [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).

Комментарии:

1. Если вы установите std::uintmax_t filesize = -1; (максимальное значение) и SPDLOG_DEBUG("{}", filesize); что вы получите?

Ответ №1:

Существует ошибка, которая будет исправлена в последних версиях MinGW. cf:

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::pathamp; p );
 

Комментарии:

1. Это ничего не меняет, у меня все то же странное значение.

2. обратите внимание, что SPDLOG_DEBUG("std::uintmax_t {}, size_t {}", std::numeric_limits<std::uintmax_t>::max(), std::numeric_limits<size_t>::max()) дайте мне одинаковый размер для двух значений : [07/12/2020 12:46:59][debug] std::uintmax_t 18446744073709551615, size_t 18446744073709551615

3. Похоже, это ошибка minGW32 / 64 reddit.com/r/cpp_questions/comments/fina0q /…

Ответ №2:

fs::file_size(filename); возвращает a std::uintmax_t . Которое, вероятно, является 64-битным целым числом. Вы присваиваете его a size_t , которое может (и, вероятно, соответствует вашей ошибке) быть 32-битным целым числом.

Просто используйте uintmax_t :

uintmax_t filesize;

Комментарии:

1. Это ничего не меняет, у меня все то же странное значение.

2. обратите внимание, что SPDLOG_DEBUG("std::uintmax_t {}, size_t {}", std::numeric_limits<std::uintmax_t>::max(), std::numeric_limits<size_t>::max()) дайте мне одинаковый размер для двух значений : [07/12/2020 12:46:59][debug] std::uintmax_t 18446744073709551615, size_t 18446744073709551615

Ответ №3:

Это может быть ошибкой MinGW32. Размер, который вы только что получили, является подписанным расширением 3202777528, вы можете проверить это значение самостоятельно:

 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 внутренне, что является псевдонимом int32_t в 32-разрядной среде. Возможно, вместо этого вам следует использовать MinGW64.

Ответ №4:

Как говорит Флоран, похоже, это ошибка. gcc 10.2 в Windows использует _wstat, который представляет собой 32-разрядную функцию. Исправление скоро появится в версии 10.3 gcc в Windows.