Как GetFreeDiskSpaceEx может вернуть (казалось бы) неправильный объем дискового пространства? - PullRequest
4 голосов
/ 25 января 2012

Поэтому я работаю на устройстве, которое выводит большие изображения (от 30 МБ до 2 ГБ +).Прежде чем приступить к созданию одного из этих образов, мы проверяем, достаточно ли места на диске через GetDiskFreeSpaceEx.Обычно (и в этом случае) мы пишем в общую папку в той же сети.При игре нет пользовательских квот на дисковое пространство.

Вчера вечером, во время подготовки к демонстрации, мы запустили тестовый запуск.Во время пробега мы потерпели неудачу.Нам потребовалось 327391776 байтов, и нам сказали, что у нас есть только 186580992.Числа от GetDiskFreeSpaceEx были:

Доступно свободное место пользователя: 186580992

Всего доступно свободного места: 186580992

Они соответствуют QuadPart переменные в двух (выходных) аргументах lpFreeBytesAvailable и lpTotalNumberOfFreeBytes до GetDiskFreeSpaceAvailable.

Этот код используется уже много лет, и я никогда не видел ложного отрицания.Вот полная функция:

long IsDiskSpaceAvailable( const char* inDirectory, 
                           const _int64& inRequestedSize, 
                           _int64& outUserFree, 
                           _int64& outTotalFree, 
                           _int64& outCalcRequest  )
{
    ULARGE_INTEGER  fba;
    ULARGE_INTEGER  tnb;
    ULARGE_INTEGER  tnfba;
    ULARGE_INTEGER  reqsize;
    string          dir;
    size_t          len;

    dir = inDirectory;
    len = strlen( inDirectory );

    outUserFree     = 0;
    outTotalFree    = 0;
    outCalcRequest  = 0;

    if( inDirectory[len-1] != '\\' )
        dir += "\\";

    // this is the value of inRequestSize that was passed in
    // inRequestedSize = 3273917760;
    if( GetDiskFreeSpaceEx( dir.c_str(), &fba, &tnb, &tnfba ) )
    {
        outUserFree         = fba.QuadPart;
        outTotalFree        = tnfba.QuadPart;

        // this is computed dynamically given a specific compression
        // type, but for simplicity I had hard-coded the value that was used
        float compressionRatio = 10.0;
        reqsize.QuadPart = (ULONGLONG) (inRequestedSize / compressionRatio);
        outCalcRequest   = reqsize.QuadPart;

        // this is what was triggered to cause the failure,
        // i.e., user free space was < the request size
        if( fba.QuadPart < reqsize.QuadPart )
            return( RetCode_OutOfSpace );
    }
    else
    {
        return( RetCode_Failure );
    }

    return( RetCode_OK );
}

Итак, функции * передано значение 3273917760, представляющее собой общий объем дискового пространства, необходимый перед сжатием.Функция делит это на степень сжатия 10 для получения необходимого фактического размера.

Когда я проверил диск, на котором находится общий ресурс, было свободно ~ 177 ГБ, что намного больше, чем сообщалось.После повторного запуска теста ничего не изменилось.

Итак, мой вопрос здесь;что может вызвать что-то подобное?Насколько я могу судить, это не ошибка программирования, и, как я упоминал ранее, этот код использовался в течение очень долгого времени без проблем.

Я проверил журнал событий удаленного компьютера.и не нашел ничего интересного во время неудачи.Я надеюсь, что кто-то там видел нечто подобное раньше, спасибо заранее.

1 Ответ

3 голосов
/ 25 января 2012

Может быть бесполезно, но странно, что:

177 ГБ ~ = 186580992 * 1000.

Это может быть объяснено повреждением стека (поскольку вы не инициализируете локальную переменную), происходящим в другом месте кода.

Код "inRequestedSize /ressionRatio" не обязательно должен использовать float для деления, и, поскольку вы отключили предупреждение «Снижение точности преобразования» при приведении, вы можете на самом деле также вызвать ошибку (но число приведенный в примере должен работать). Вы можете просто сделать "inRequestedSize / 10".

И последнее, но не менее важное: вы не говорите, где работает код. На мобильном устройстве документация GetDiskFreeSpaceEx гласит:

Когда мобильное шифрование включено, поведение отчетов этой функции изменяется. С каждым зашифрованным файлом связана как минимум одна страница объемом 4 КБ. Эта функция учитывает эти издержки, когда сообщает о доступном пространстве. То есть, если на диске объемом 128 КБ содержится один файл размером 60 КБ, эта функция сообщает о наличии 64 КБ, вычитая пространство, занимаемое как файлом, так и соответствующими издержками.

Несмотря на то, что эта функция сообщает об общем доступном пространстве, учитывайте требования к месту для зашифрованных файлов при оценке того, поместятся ли несколько новых файлов в оставшееся пространство. Включите объем пространства, необходимого для служебных данных, когда включено мобильное шифрование. Каждый файл требует как минимум дополнительные 4 КБ. Например, для одного файла размером 60 КБ требуется 64 КБ, а для двух файлов размером 30 КБ фактически требуется 68 КБ.

...