使用CreateFile/ReadFile遇错误998:无效内存访问求助
Hey Sergio, sorry to hear you're stuck on this error—let's break down exactly what's causing it and how to fix it, since this is a super common pitfall when you're first working with Win32 file I/O!
Why Error 998 Happens Here
Error code 998 (INVALID_ACCESS_TO_MEMORY_LOCATION) almost always means your ReadFile call is trying to write to memory it doesn't have permission to access, or you're passing an invalid pointer as one of the parameters. For your scenario, the most likely culprits are:
- Using a read-only memory buffer as the output destination for
ReadFile - Passing an invalid file handle from
CreateFile(without checking if it succeeded) - Using an uninitialized or invalid pointer for the
lpNumberOfBytesReadparameter
Step-by-Step Fixes & Example Code
1. First: Validate Your CreateFile Handle
Never assume CreateFile succeeded! If it fails (returns INVALID_HANDLE_VALUE), using that handle for ReadFile will cause all sorts of weird errors, including 998. Always check the return value and log the error code if it fails.
2. Use a Writable Buffer (The #1 Cause of This Error)
This is the mistake most new Win32 developers make: if you pass a pointer to a string literal (like char* buffer = "Hello, world";) to ReadFile, you're trying to write to read-only memory (string literals are stored in a protected data segment). Instead, allocate a writable buffer on the stack or heap.
3. Ensure lpNumberOfBytesRead Is a Valid Pointer
ReadFile needs a valid pointer to a DWORD variable to store how many bytes were read. Don't pass NULL here unless you're using asynchronous I/O (which you're probably not for this simple case).
Working Example Code
Here's a complete, tested example that should work for your scenario:
#include <windows.h> #include <stdio.h> int wmain(int argc, wchar_t* argv[]) { // Verify we got the file path as a command-line argument if (argc < 2) { wprintf(L"Usage: %s <file path>\n", argv[0]); return 1; } // Open the file with correct access flags HANDLE hFile = CreateFileW( argv[1], // Command-line path argument GENERIC_READ, // Request read access FILE_SHARE_READ, // Allow other processes to read the file NULL, // Default security attributes OPEN_EXISTING, // Only open if the file already exists FILE_ATTRIBUTE_NORMAL, // Regular file attributes NULL // No template file ); // Check if CreateFile succeeded if (hFile == INVALID_HANDLE_VALUE) { wprintf(L"CreateFile failed! Error code: %lu\n", GetLastError()); return 1; } // Allocate a writable buffer on the stack (plenty big for "Hello, world") char buffer[1024] = {0}; // Initialize to zero to avoid garbage at the end DWORD bytesRead = 0; // Read the file content BOOL readSuccess = ReadFile( hFile, // Valid file handle buffer, // Writable buffer (critical!) sizeof(buffer)-1, // Leave 1 byte for the null terminator &bytesRead, // Valid pointer to store bytes read NULL // Synchronous I/O, no overlapped structure ); if (!readSuccess) { wprintf(L"ReadFile failed! Error code: %lu\n", GetLastError()); CloseHandle(hFile); return 1; } // Output the result to the console printf("Read content: %s\n", buffer); // Always close the file handle when done! CloseHandle(hFile); return 0; }
Key Takeaways to Avoid This Error Again
- Never write to read-only memory: Use stack-allocated arrays or heap-allocated memory for
ReadFile's output buffer. - Validate every Win32 API call: Always check return values like
CreateFile's handle andReadFile's success flag. - Use wide-string functions (
CreateFileW): If you're passing paths with non-ASCII characters (or even just standard paths on modern Windows), wide strings avoid path parsing issues. - Clean up resources: Don't forget to call
CloseHandlewhen you're done with the file handle to avoid leaks.
内容的提问来源于stack exchange,提问作者Sergio Calderon

