Ответ 1
Если вы выделяете 5,1 ГБ, вам лучше убедиться, что вы скомпилировали свой код в 64 бита и запустили его в 64-битной версии Windows. Ohterwhise, память адресное пространство ограничено до max 3 ГБ на 32 битах Windows и 4 ГБ с 32-битным кодом на 64-битной Windows.
Кстати, ftell()
возвращает подписанный long
. Вы должны проверить, что здесь нет ошибки (например, переполнение, если ОС позволяет увеличить размер файла), так что значение не равно -1.
Изменить:
Обратите внимание, что с MSVC, long
будет в настоящее время содержать 32-битное число, даже если скомпилировано для 64 бит. Это означает, что ftell()
даст вам значимый результат, если размер файла ниже 2 ГБ (потому что для знака).
Для получения размера больших файлов в подписанном 64-битовом номере вы можете использовать неконсервативную ОС WinAPI GetFileSizeEx()
.
malloc()
принимает size_t
, который является unsigned 64-разрядным номером. Так что с этой стороны вы в безопасности.
Альтернативой будет использование сопоставление файлов.
Второе редактирование
Я просмотрел ваши изменения о ценности, полученной для размера, которые отличаются от ожидаемого. Я мог воспроизвести ошибку в моей системе и получил размер, который не был нулевым, но это был номер, намного больший, чем файл.
Рассматривая эту рекомендацию по безопасности CERT, оказалось, что гарантии, предлагаемые стандартом для fseek()
в сочетании с SEEK_END
, являются недостаточными и сделать это очень опасным подходом.
Итак, пусть повторяется: самым простым способом получить размер будет использование встроенной функции OS i.e. GetFileSizeEx()
в Windows. Там обходной путь для 64-битных окон: используйте _fseeki64()
и _ftelli64()
:
...
if (_fseeki64(pFile, 0, SEEK_END)) {
fputs("File seek error", stderr);
return (1);
}
lSize = _ftelli64(pFile); // RETURNS EXACT SIZE
...
Это работало очень хорошо (исходная проблема, казалось, была связана с типом возвращаемого значения, который был недостаточно большим). Однако имейте в виду, что это обходной путь, и я боюсь, что могут быть другие ошибки, которые могут привести к уязвимости, о которой сообщает CERT.