是什么导致 fstream::open 在这里失败?
What is causing fstream::open to fail here?
问题
我正在 Win32 C++ 中开发一个简单的记事本应用程序。但是我 运行 在打开要保存的文件时遇到了问题。有相当多的代码(您可以找到 here)但是导致错误的行在文件 Event Handlers.cpp
.
中
具体来说,第 25 行
wnd.file.open(wnd.filePath, std::ios_base::out);
抛出异常。这是调试输出:
Exception thrown: read access violation.
this->**_Ptr** was nullptr.
尽管 _Ptr
并不总是值 nullptr
。
我试过的
这就是问题的要点。现在这是我到目前为止尝试过的方法。
- 正在检查另存为对话框的结果(
wnd.filePath
的值)——确实是正确的文件路径字符串
- 打开前刷新、清除、关闭文件流
- 改变打开方式
- 我想也许
fstream
对象不能是全局的,因为我注意到 std::filebuf
成员对于全局 fstreams 总是 NULL 而不是本地 fstreams。这实际上不是问题。
- 以及过去几天的许多其他事情,不幸的是我不记得了
我的理论
但是,我认为问题出在我的代码设计和 std::fstream
class。
Main.cpp
中的第 34 行:
mainWnd = TopLevelWnd(wr.left, wr.right, wr.left, wr.top, 1280, 720, wr.right - wr.left,
wr.bottom - wr.top, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
0, L"Main Window Class", L"Main Window", hInstance);
构造一个TopLevelWnd
,然后复制到全局向量windows
中默认构造的TopLevelWnd
。据我所知,class std::fstream
已删除其复制成员,无法复制。这应该会产生编译器错误,因为它是 TopLevelWnd
的成员,但它不会。无论如何,我决定删除 TopLevelWnd
的复制成员并编写移动构造函数和移动赋值运算符函数并使用 std::move
:
显式调用它们
// delete copy members because fstream cannot be copied
TopLevelWnd& operator=(const TopLevelWnd&) = delete;
TopLevelWnd(const TopLevelWnd&) = delete;
// move members
TopLevelWnd(TopLevelWnd&& source)
: Wnd(std::move(source)),
file(std::move(source.file))
{}
TopLevelWnd& operator=(TopLevelWnd&& right)
{
Wnd::operator=(std::move(right));
file = std::move(right.file);
return *this;
}
这也没有解决问题,所以我完全不知所措。有人可以帮我理解吗?
P.S。顺便说一句,要重现问题,您只需 运行 程序,然后在菜单中转到文件 -> 保存并选择一个文件来保存。
经过大量的挖掘和试验,我终于找到了答案。问题出在 TopLevelWnd
构造函数中。
TopLevelWnd(int x, int y, int ncX, int ncY, int width, int height, int ncWidth, int ncHeight, DWORD styles, DWORD exStyles, const wchar_t* className, const wchar_t* name, HINSTANCE hInstance = GetModuleHandleW(nullptr), HWND hWnd = nullptr, HWND hWndParent = nullptr, HMENU hMenu = nullptr)
: Wnd(x, y, ncX, ncY, width, height, ncWidth, ncHeight, styles, exStyles, className, name, hInstance ,hWnd, hWndParent),
hMenu(hMenu)
它有两个参数,名为 hWnd
和 hMenu
。 class 还有两个数据成员 hWnd
和 hMenu
。在正文中,我写的行如下:
hWnd = CreateWindowExW(...);
hMenu = CreateMenu();
当我需要写作时
this->hWnd = CreateWindowExW(...)
this->hMenu = CreateMenu();
问题
我正在 Win32 C++ 中开发一个简单的记事本应用程序。但是我 运行 在打开要保存的文件时遇到了问题。有相当多的代码(您可以找到 here)但是导致错误的行在文件 Event Handlers.cpp
.
具体来说,第 25 行
wnd.file.open(wnd.filePath, std::ios_base::out);
抛出异常。这是调试输出:
Exception thrown: read access violation.
this->**_Ptr** was nullptr.
尽管 _Ptr
并不总是值 nullptr
。
我试过的
这就是问题的要点。现在这是我到目前为止尝试过的方法。
- 正在检查另存为对话框的结果(
wnd.filePath
的值)——确实是正确的文件路径字符串 - 打开前刷新、清除、关闭文件流
- 改变打开方式
- 我想也许
fstream
对象不能是全局的,因为我注意到std::filebuf
成员对于全局 fstreams 总是 NULL 而不是本地 fstreams。这实际上不是问题。 - 以及过去几天的许多其他事情,不幸的是我不记得了
我的理论
但是,我认为问题出在我的代码设计和 std::fstream
class。
Main.cpp
中的第 34 行:
mainWnd = TopLevelWnd(wr.left, wr.right, wr.left, wr.top, 1280, 720, wr.right - wr.left,
wr.bottom - wr.top, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
0, L"Main Window Class", L"Main Window", hInstance);
构造一个TopLevelWnd
,然后复制到全局向量windows
中默认构造的TopLevelWnd
。据我所知,class std::fstream
已删除其复制成员,无法复制。这应该会产生编译器错误,因为它是 TopLevelWnd
的成员,但它不会。无论如何,我决定删除 TopLevelWnd
的复制成员并编写移动构造函数和移动赋值运算符函数并使用 std::move
:
// delete copy members because fstream cannot be copied
TopLevelWnd& operator=(const TopLevelWnd&) = delete;
TopLevelWnd(const TopLevelWnd&) = delete;
// move members
TopLevelWnd(TopLevelWnd&& source)
: Wnd(std::move(source)),
file(std::move(source.file))
{}
TopLevelWnd& operator=(TopLevelWnd&& right)
{
Wnd::operator=(std::move(right));
file = std::move(right.file);
return *this;
}
这也没有解决问题,所以我完全不知所措。有人可以帮我理解吗?
P.S。顺便说一句,要重现问题,您只需 运行 程序,然后在菜单中转到文件 -> 保存并选择一个文件来保存。
经过大量的挖掘和试验,我终于找到了答案。问题出在 TopLevelWnd
构造函数中。
TopLevelWnd(int x, int y, int ncX, int ncY, int width, int height, int ncWidth, int ncHeight, DWORD styles, DWORD exStyles, const wchar_t* className, const wchar_t* name, HINSTANCE hInstance = GetModuleHandleW(nullptr), HWND hWnd = nullptr, HWND hWndParent = nullptr, HMENU hMenu = nullptr)
: Wnd(x, y, ncX, ncY, width, height, ncWidth, ncHeight, styles, exStyles, className, name, hInstance ,hWnd, hWndParent),
hMenu(hMenu)
它有两个参数,名为 hWnd
和 hMenu
。 class 还有两个数据成员 hWnd
和 hMenu
。在正文中,我写的行如下:
hWnd = CreateWindowExW(...);
hMenu = CreateMenu();
当我需要写作时
this->hWnd = CreateWindowExW(...)
this->hMenu = CreateMenu();