【问题标题】:Why do I get an access violation when using the ReadFile() function? [duplicate]为什么在使用 ReadFile() 函数时会出现访问冲突? [复制]
【发布时间】:2023-03-24 21:54:01
【问题描述】:

我一直在尝试从文件中读取,我正在使用 Windows API 函数 ReadFile()。我使用了以下代码:

int main()
{
    LPDWORD bytesRead = 0;
    HANDLE hFile = CreateFile("TestFile.txt", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);

    char Data[600];

    ReadFile(hFile, Data, 10, bytesRead, 0);

    cout << Data;
    cin.get();
}

当我执行这段代码时,它会引发访问冲突!

这是为什么?我觉得我正确使用了ReadFile() - 但我可能错了。我该如何解决这个错误(如何正确使用ReadFile())?

【问题讨论】:

  • 你可能想写char Data[600] = {0};而不是char Data[600];
  • 缺少错误检查也是个问题。
  • 您的cout &lt;&lt; Data; 有问题。该版本的operator&lt;&lt; 用于 C 风格的字符串,而不是任意数据。
  • 由于lpNumberOfBytesRead 参数无效,Crash when calling ReadFile 可能重复。

标签: c++ windows winapi


【解决方案1】:

ReadFile 的第四个参数是指向DWORD 的指针。你给了它一个指针,但它是空的——它实际上并不指向DWORD

DWORD bytesRead = 0;
...
ReadFile(hFile, Data, 10, &bytesRead, 0);

【讨论】:

  • 成功了!谢谢,我会在 7 分钟内将其作为答案,因为 stackoverflow 不允许我在 3 分钟内接受答案:)
【解决方案2】:

这可能不是你的主要问题,但你应该写:

char Data[600] = {0};

代替:

char Data[600];

后一个语句使您的数组未初始化。然后,执行后 ReadFile(),您的字符串可能不会被 \0 字符终止。在这种情况下,cout 在 10 个字节后不会停止打印。在最坏的情况下,您会在这里遇到另一个访问冲突。


正如@DavidHeffernan 在 cmets 中提到的,以下解决方案将比初始化整个数组更有效:

DWORD bytesRead = 0;
ReadFile(hFile, Data, 10, &bytesRead, 0);
Data[bytesRead] = '\0';

通过在最后一行使用bytesRead,您可以确保数据被\0字符正确终止,即使不是所有请求的10字节都被读取(例如,因为文件短于10字节)。但是,在您的实际代码中,您还应该检查ReadFile() 的返回值,以验证读取是否成功。如果失败,您可能需要进行一些错误处理。

【讨论】:

  • 我不建议初始化整个缓冲区。那将是低效的。只需在读取的数据后写入一个零字节即可。
  • 输出未终止的字符串可能会导致访问冲突。
  • 如果文件小于 10 字节,这仍然会访问未初始化的数据。
  • @RaymondChen:感谢您的提示!我相应地改进了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多