c++ - 在析构函数中调用 CloseHandle 会导致运行时内存错误,如何正确关闭结构/类中的文件句柄?

标签 c++ oop winapi handle

错误信息是:“0x7c810eac”处的指令引用了“0x00000000”处的内存。无法“写入”内存。

如果我删除析构函数,一切都很好。但我不明白这里发生了什么。我到处都读到我应该关闭句柄,但这里的代码不允许我这样做。 (是的,我知道我可以手动完成...但这是客户端代码中不必要的一行,我认为应该由对象处理。)

#include <windows.h>
#include <iostream>
#include <string>

struct fileHandle {
  HANDLE hFile;
  fileHandle(std::string path) {
    hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
      printf("error: INVALID_HANDLE_VALUE");
    }
  }
  ~fileHandle() {
    CloseHandle(hFile);
  }
  void save(std::string data) {
    if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
      printf("WriteFile failed: ", GetLastError());
    }
  }
};

int main() {
  fileHandle my_handle("test_file.txt");
  my_handle.save("some text");
}

更新:当文件不存在时会发生这种情况。当文件确实存在时程序打印错误,但这是有意的。我在这里询问 co cover only this case when file is created(我知道如何重写 handle creating 以覆盖现有文件。)

编译器:http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev7.7z

更新 2:我没有提到这段代码可以工作并写入文件。最后触发内存错误。

最佳答案

请使用 -Wall 编译所有代码。节省了大量时间。

在您的代码 printf 中有一个无效的格式字符串。 printf 的正确解决方案是(注意 %lu):

void save(std::string data) {
  if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
    printf("WriteFile failed: %lu", GetLastError());
  }
}

如果您使用 -Wall 进行编译,您的代码会发出警告:

filehandle.cpp: In member function 'void fileHandle::save(std::string)':
filehandle.cpp:18:50: warning: too many arguments for format [-Wformat-extra-args]

您还应该将错误打印到 stderr,因为它是无缓冲的。 printf 使用缓冲区,这就是您没有得到任何输出的原因。在错误之后添加 \n 也是一个好主意。

另请阅读其他答案以改进您的代码。使用 rule of three .


阅读评论后,我意识到这确实不是段错误的原因。 (另请参阅 Ron Burk 的解决方案,看看哪里出了问题。)

根据 Windows API 文档,lpNumberOfBytesWritten 参数只有在 lpOverlapped 参数 不为 NULL 时才能为 NULL >.

所以你必须给出一个指向 DWORD 的指针,WriteFile 可以在其中存储它实际读取的字节数。最终保存为:

void save(std::string data) {
  DWORD writtenBytes;
  if (!WriteFile(hFile, data.c_str(), data.size(), &writtenBytes, NULL)) {
    printf("WriteFile failed: %lu", GetLastError());
  }
}

如果文件存在,则不会弹出错误,因为将 INVALID_HANDLE_VALUE 传递给 WriteFile 似乎会使 WriteFile 在使用您的指针之前返回。

关于c++ - 在析构函数中调用 CloseHandle 会导致运行时内存错误,如何正确关闭结构/类中的文件句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14803155/

相关文章:

java - JFrame.setExtendedState(MAXIMIZED_BOTH) 是否适用于未修饰的框架?

c++ - 不同 gcc 版本的 unordered_map 大小不同

c++ - 如何将 gst-rtsp-server 与自己的管道一起使用?

javascript - 经典与原型(prototype)继承

java - 如何在 JFrame 中动态重绘 JPanel?

winapi - 使用 WS_EX_COMPOSITED 选项卡控制高 CPU 使用率

c++ - 使用 NDK 将选择循环应用程序移植到 Android。设计问题

c++ - boost 图 : How to copy the nodes and edges of a graph without copying properties?

java - 同名调用的非覆盖子类方法

c++ - 在 win32 中发送十六进制值不能像 C++ 代码那样工作