【问题标题】:Access violation when writing struct to file将结构写入文件时访问冲突
【发布时间】:2016-05-18 20:05:58
【问题描述】:

我有一个“书”结构,其中包含可用书籍的作者、名称和数量。

struct book {
    TCHAR author[32];
    TCHAR name[32];
    SHORT count;
    void insert() {
        cout << "Book author: "; wscanf_s(L"%s", author, _countof(author));
        cout << "Book name: "; wscanf_s(L"%s", name, _countof(name));
        cout << "Book count: ";  wscanf_s(L"%i", count);
    }
    void get() {
        cout << "Book info: " << endl;
        wprintf(L"\nAuthor - %s", author);
        wprintf(L"\nName - %s", name);
        wprintf(L"\nCount - %i", count);
        cout << endl;
    }
};

任务让我制作一个 DAT 文件,然后在其中添加“书籍”。

HANDLE hFile = CreateFile(_TEXT("C:\\Students\\book.dat"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(hFile, 0, 0, FILE_END);
book newBook;
DWORD bytesWritten;
newBook.insert();
WriteFile(hFile, &newBook, sizeof(book), &bytesWritten, NULL);
FindClose(hFile);

但是,每当我这样做时,我都会收到一个错误:

访问冲突写入位置 0xFFFFFEFE。

我在这里做错了什么?

【问题讨论】:

  • 您确实应该检查来自这些 API 调用的所有的返回值,以确保一切正常。
  • 除了进行错误检查的 scanf 错误之外,还使用早已过时的 TCHAR,使用原始 Win32 IO 而不是 C++ IO 并编写未初始化的结构。
  • 我应该尽可能使用原始 Win32 方法。如果我有选择,我不会使用这些。将添加错误检查。

标签: c++ winapi


【解决方案1】:

这一行

cout << "Book count: ";  wscanf_s(L"%i", count);

应该是

cout << "Book count: ";  wscanf_s(L"%i", &count);

您可能还应该检查文件是否打开:

HANDLE hFile = CreateFile(_TEXT("C:\\Students\\book.dat"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
    cerr << "Unable to open file\n";
    exit(1);
}

--- 编辑 ---

使用您的代码,Visual Studio 会给出以下警告:

c:\dev\test\test.cpp(14): 警告 C4477: 'wscanf_s' : 格式字符串 '%i' 需要类型为 'int *' 的参数,但可变参数 1 的类型为 'SHORT *'

c:\dev\test\test.cpp(14): 注意:考虑在格式字符串中使用'%hi'

这是什么意思

cout << "Book count: ";  wscanf_s(L"%i", &count);

应该是

cout << "Book count: ";  wscanf_s(L"%hi", &count);

或者你应该计算一个 DWORD。

【讨论】:

  • 已更改,已添加。现在阅读:SysLab4.exe 中 0x77D22312 (ntdll.dll) 的第一次机会异常:0xC0000005:访问冲突写入位置 0xFEFEFF1E。
  • 您是忽略编译器警告还是没有打开“输出”窗口?
  • 将计数更改为 DWORD。仍然出现访问冲突...编译器仅在第 105 行和第 121 行警告有符号/无符号不匹配,并在第 122 行转换为 SHORT。Full code here
  • VCib,此时您正在移动球门柱。建议使用a minimal complete and verifiable example 提出新问题。或者启动开发环境附带的调试器和start debugging
【解决方案2】:

访问冲突是因为您在使用CreateFile 打开的句柄上调用FindCloseFindClose 仅用于关闭通过FindFirstFile 获得的句柄。

您需要改为致电CloseHandle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2011-12-04
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多