错误信息是:“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 以覆盖现有文件。)
更新 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/