使用 ReadFile 对内存位置的无效访问

Posted

技术标签:

【中文标题】使用 ReadFile 对内存位置的无效访问【英文标题】:Invalid access to memory location with ReadFile 【发布时间】:2018-02-06 18:54:35 【问题描述】:

我有一个文件,C:\demo\Demo.txt,上面有一个简单的“Hello, world”。我想将路径作为参数传递给我的应用程序,用CreateFile 打开它,用ReadFile 读取它并在控制台上显示该行。但是,我收到错误代码998

对内存位置的访问无效。

这是我的代码:

int wmain(int argc, WCHAR **argv)

    if (argc != 2)
    
        fwprintf(stderr, L"\nWrong arguments. \n");
        return 1;
    

    // CreateFile function variables
    HANDLE hSourceFile;
    LPCWSTR fileName = (LPCWSTR)argv[1];
    DWORD desiredAccess = FILE_GENERIC_READ;
    DWORD shareMode = FILE_SHARE_READ;
    DWORD creationDisposition = OPEN_EXISTING;
    DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;

    //---------------------------------------------------------------
    // Opening file for reading data
    hSourceFile = CreateFileW(
        fileName,
        desiredAccess,
        shareMode,
        NULL,
        creationDisposition,
        flagsAndAttributes,
        NULL);

    if (hSourceFile != INVALID_HANDLE_VALUE)
    
        wprintf(L"\nThe source file, %s, is open. \n", fileName);
    
    else
    
        wprintf(L"Error code: %u\n", GetLastError());
    

    // ReadFile function variables
    LPVOID dataRead=NULL;
    DWORD bytesToRead = 100;
    DWORD bytesWritten = 0;

    //-----------------------------------------------------------------
    // Reading data from file
    if (!ReadFile(
        hSourceFile,
        dataRead,
        bytesToRead,
        &bytesWritten,
        NULL))
    
        wprintf(L"Error code: %u\n", GetLastError());
        return 1;

    

    wprintf(L"%s. \n", (LPWSTR)dataRead);   


    CloseHandle(hSourceFile);

    return 0;

我第一次使用ReadFile,所以不知道我做错了什么。

你能帮帮我吗?

【问题讨论】:

LPVOID dataRead=NULL; -> char dataRead[100];ReadFile 想要一个指向有效内存的指针。 其他不相关的问题:如果hSourceFile == INVALID_HANDLE_VALUE 打印了错误代码,但随后您继续使用ReadFile,这毫无意义。并且您打印dataRead 缓冲区的内容,而没有确保有一个NUL 终止符。而如果你读到的文件不是用DBCS(双字节字符串)编码的,你就会打印垃圾。 您是否希望ReadFile 更改dataRead 的值?如果它要更改存储在dataRead 中的值,它不会采用指向dataRead 的指针而不是它的值吗? 【参考方案1】:

ReadFile 想要一个指向可以写入数据的缓冲区的指针。你传递的是 NULL,所以你得到了你看到的错误。

我会把代码改成

    // ReadFile function variables
    static const DWORD bytesToRead = 100;
    unsigned char dataRead[bytesToRead];
    DWORD bytesWritten = 0;

    //-----------------------------------------------------------------
    // Reading data from file
    if (!ReadFile(
        hSourceFile,
        dataRead,
        bytesToRead,
        &bytesWritten,
        NULL))
    
        wprintf(L"Error code: %u\n", GetLastError());
        return 1;
    

您遇到的下一个问题是您将指针转换为LPWSTR,即指向空终止 宽字符串的指针。您的文件是否包含该空终止?还是您需要自己添加?假设文件 包含终止,您可能想要:

    // ReadFile function variables
    static const DWORD bufferSize = 50;
    WCHAR buffer[bufferSize+1];  // Leave room for null.
    DWORD bytesWritten = 0;

    //-----------------------------------------------------------------
    // Reading data from file
    if (!ReadFile(
        hSourceFile,
        buffer,
        bufferSize*sizeof(WCHAR),
        &bytesWritten,
        NULL))
    
        wprintf(L"Error code: %u\n", GetLastError());
        return 1;
    
    buffer[bytesWritten/sizeof(WCHAR)] = 0; // Null terminate.
    wprintf(L"%s. \n", buffer);  // Look ma!  No cast needed.

【讨论】:

试过了,但它正在打印 ??????????。我试图从 LPVOID 转换为 LPWSTR,以便打印。【参考方案2】:

您必须分配一个内存缓冲区来放置读取字节。现在你的指针 dataRead 指向 nullptr,换句话说,没有任何地方,但是你传递了大小 100,这表明你的指针指的是 100 字节分配的缓冲区,这不是事实。

【讨论】:

我添加了PBYTE dataRead = (BYTE*)malloc(bytesToRead); 并打印了wprintf(L"%s. \n", (WCHAR*)dataRead);,但我收到了这样的信息:??????? @SergioCalderon : a) 文件是否包含wprintf 需要的空终止符; b) 文件中实际上是什么?是 WCHAR 字符还是简单的 ASCII? (我会说“用od -c 转储它,但是就像你在Windows 上一样,除非你有cygwin,否则你不会有od 我没有将文件保存为 UNICODE,谢谢。

以上是关于使用 ReadFile 对内存位置的无效访问的主要内容,如果未能解决你的问题,请参考以下文章

Windows Vista:无法加载 DLL“x.dll”:对内存位置的访问无效。 (DllNotFoundException)

对内存空间的理解

计算对内存的读写访问

CPU和内存之间的通信是怎么实现的?CPU对内存的访问时如何实现的? 大学考题,务必精确啊,谢谢

使用 ReadFile 时访问冲突读取位置

Linux DMA访问的一致性