Сбой при вызове ReadFile после LockFileEx

0

У меня есть несколько процессов, которые пытаются читать и записывать один и тот же файл. Я хочу, чтобы каждый из них блокировал файл, чтобы только один из них обращался к нему за раз.

Я попробовал это (отредактируйте: на этот раз это полный тестовый код):

#include "stdafx.h"
#include "Windows.h"


bool test()
{
        const char* path = "test.txt";

        HANDLE hFile = CreateFileA(path,
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL,
                        OPEN_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);

        if (hFile == INVALID_HANDLE_VALUE)
        {
                printf("ERROR: Cannot open file %s\n", path);
                return false;
        }

        // Lock the file
        {
                OVERLAPPED overlapped = {0};
                BOOL res = LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, ~0, ~0, &overlapped);
                if (!res)
                {
                        printf("ERROR: Cannot lock file %s\n", path);
                        return false;
                }
        }

        DWORD fileSize = GetFileSize(hFile, NULL);
        if (fileSize > 0)
        {
                char* content = new char[fileSize+1];

                // Read the file
                BOOL res = ReadFile(hFile, content, fileSize, NULL, NULL);
                if (!res)
                {
                        printf("ERROR: Cannot read file %s\n", path);
                }

                delete[] content;
        }


        const char* newContent = "bla";
        int newContentSize = 3;

        // Write the file
        BOOL res = WriteFile(hFile, newContent, newContentSize, NULL, NULL);
        if (!res)
        {
                //int err = GetLastError();
                printf("ERROR: Cannot write to file\n");
        }

        // Unlock the file
        {
                OVERLAPPED overlapped = {0};
                UnlockFileEx(hFile, 0, ~0, ~0, &overlapped);
        }

        CloseHandle(hFile);

        return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
        bool res = test();

        return 0;
}

Это отлично работает на моем компьютере, который имеет Windows 8. Но на компьютере моего коллеги, который имеет Windows 7, он сбой. В частности, всегда возникают сбои в ReadFile и WriteFile.

Обратите внимание, что он никогда не входит в коды кода с ошибкой printfs. Этот код не вызывает ошибки, кроме записи в местоположении 0x00000000 в ReadFile (при запуске в Windows 7).

Мы также попытались передать перекрываемую структуру на вызовы ReadFile и WriteFile. Он предотвращает крах, но блокировка больше не работает, файл все скремблирован (не с этим тестовым кодом, с реальным кодом).

Что я делаю не так?

  • 2
    Не проверка возвращаемых результатов и GetLastError ().
  • 0
    Включите полный код и будьте конкретны. Это сбой на ReadFile или WriteFile ? Это не может разбиться на обоих.
Показать ещё 11 комментариев
Теги:
winapi

2 ответа

4
Лучший ответ

Похоже, ваша проблема:

Параметр lpNumberOfBytesRead [out, optional] имеет значение null в вашем вызове.

Этот параметр может быть NULL, только если параметр lpOverlapped не равен NULL.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx

  • 0
    Большое спасибо, это то, что я пропустил! Это также объясняет, почему это работало при добавлении overalapped параметра.
-1

Вот ваша проблема:

Вам не хватает необходимого структурного члена и:

0 и ~0 и {0} - все плохие коды, постоянные выражения, подобные этим, всегда будут давать неизведанные результаты - WINAPI не работает как libc, параметры не всегда сравниваются с константами, вместо этого они проверяются с помощью макросов и других препроцессоров, сами определения, передающие постоянные значения или инициализирующие структуры WINAPI с константами, часто приводят к таким ошибкам.

После нескольких лет экспериментов я обнаружил, что есть только один верный способ избежать их, я буду выражать его в исправленном коде:

OVERLAPPED overlapped;
overlapped.hEvent = CreateEvent( ........... ); // put valid parameters here!
UnlockFileEx(hFile, 0 /*"reserved"*/, ULONG_MAX, ULONG_MAX, &overlapped);

внимательно прочитайте это: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365716%28v=vs.85%29.aspx

  • 0
    Что ж, в документации на самом деле сказано, что я должен инициализировать членов на 0. И для hEvent в нем сказано конкретно: вы должны инициализировать член hEvent для допустимого дескриптора или нуля . Я попробую ваш метод, потому что у меня нет другой идеи, но я не пытаюсь выполнять асинхронный ввод-вывод, поэтому я не уверен, что он будет актуален.
  • 0
    попробуйте NULL вместо нуля - и выбросьте {0}
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню