AccessViolationException при использовании FileRead API - PullRequest
0 голосов
/ 04 декабря 2011

Я использую FileRead API. Я использовал Windows 7 x64, и мой код работал хорошо и правильно. Теперь я установил новый Windows 7 x86 и VS2008 teamsuit и .NET 2, 3 + SP1 + SP2, 3.5, 3.5.1. Я запускаю свой код от имени администратора, но все еще сталкиваюсь с следующей ошибкой:

AccessViolationException (Попытка чтения или записи защищенной памяти. Это часто указывает на повреждение другой памяти.)

 int nread = 0;
 uint handle;
 byte[] buff = new byte[1024];
 string driveRoot = string.Concat("\\\\.\\", driveLetter);
 uint hRoot = CreateFile(driveRoot,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                IntPtr.Zero,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                IntPtr.Zero);
 if (hRoot != -1)
      handle = ReadFile(hRoot, buff, 1024, nread, new System.Threading.NativeOverlapped());

Ответы [ 2 ]

1 голос
/ 04 декабря 2011

Хотя я не гуру в C #, мне кажется, что вы вызываете ReadFile() с неправильными параметрами.

4-й параметр должен быть указателем на целое число, которое получит количество байтовчитать.Вы задаете само целое число (nread), а не его адрес (&nread).

И если вы не хотите асинхронного файлового ввода-вывода, последний параметр для ReadFile() должен быть указателем NULL (илипросто 0).

См. этот пример на MSDN .

0 голосов
/ 04 декабря 2011

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

Я уверен, что вы не хотите перекрывающихся операций ввода-вывода, поэтому вы должны просто передать NULL в конечный параметр ReadFile.

С другой стороны, возможно, ваш код вообще не работает в системе x64 и никогда не достигает уровня AV. Ваши типы дескрипторов ошибочно объявлены как 32-битные целые числа.

Есть много других мелких проблем с вашим кодом. Вот отредактированная версия кода, которая исправляет эти ошибки. Подписи P / invoke были взяты с pinvoke.net.

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr SecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    IntPtr hTemplateFile
);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(
    IntPtr hFile, 
    [Out] byte[] lpBuffer,
    uint nNumberOfBytesToRead, 
    out uint lpNumberOfBytesRead, 
    IntPtr lpOverlapped
);

static void Main(string[] args)
{
    string physicalDrive = @"\\.\PhysicalDrive0";
    IntPtr hFile = CreateFile(
        physicalDrive, 
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        IntPtr.Zero
    );
    if (hFile.ToInt64() != INVALID_HANDLE_VALUE)
    {
        byte[] buff = new byte[1024];
        uint nread;
        if (ReadFile(hFile, buff, (uint)buff.Length, out nread, IntPtr.Zero))
            Console.WriteLine("Read successful");
    }
}

Чтобы суммировать ошибки в вашем коде:

  • Неправильное использование 32-битных целых чисел для хранения дескрипторов.
  • Ваше объявление P / invoke для ReadFile неправильно объявляет lpNumberOfBytesRead.
  • ReadFile не возвращает дескриптор, он возвращает логическое значение, указывающее на успешность вызова функции.
  • Использование перекрывающегося ввода-вывода, который вам не нужен и который не может работать с маршализованным буфером byte[].
  • Вы никогда не должны вызывать GetLastError из управляемого кода (вы сделали это в коде, указанном в комментарии). Вместо этого позвоните Marshal.GetLastWin32Error. Причины объяснены в документации для этого метода.
...