遵循官方 Direct2D 示例,但出现访问冲突错误
follow official direct2d sample but got access violation error
按照Direct2D(https://learn.microsoft.com/en-us/windows/win32/direct2d/direct2d-quickstart(的官方教程使用Visual Studio 2019创建一个示例项目。在 x86 中运行代码时,在.cpp将平台更改为 x64 时一切正常,我收到一个错误,指出:"引发异常:读取访问冲突"。(该行在下面的代码中进行了注释(
错误是:
Exception thrown: read access violation.
this was 0xBB18F6E8.
LRESULT CALLBACK DemoApp::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
if (message == WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
DemoApp* pDemoApp = (DemoApp*)pcs->lpCreateParams;
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
PtrToUlong(pDemoApp)
);
result = 1;
}
else
{
DemoApp* pDemoApp = reinterpret_cast<DemoApp*>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
bool wasHandled = false;
if (pDemoApp)
{
switch (message)
{
case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pDemoApp->OnResize(width, height); // throw the error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
result = 0;
wasHandled = true;
break;
case WM_DISPLAYCHANGE:
{
InvalidateRect(hwnd, NULL, FALSE);
}
result = 0;
wasHandled = true;
break;
case WM_PAINT:
{
pDemoApp->OnRender();
ValidateRect(hwnd, NULL);
}
result = 0;
wasHandled = true;
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
result = 1;
wasHandled = true;
break;
}
}
if (!wasHandled)
{
result = DefWindowProc(hwnd, message, wParam, lParam);
}
}
return result;
}
不幸的是,我不是WinAPI专家,但出于好奇,我用谷歌搜索了一下。现在,我很确定OP问题:
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
PtrToUlong(pDemoApp)
);
具体PtrToUlong(pDemoApp)
.
这可能适用于 32 位应用程序,但不适用于 64 位应用程序。
long
采用MS VC++ 32位 - 适用于x86和x64平台。
因此,将指针转换为long
或unsigned long
有利于在 x64 上出错(只要高 32 位不是 0 – 这可能很难预测(。
谷歌搜索这个方向,我发现例如PtrToUlong Q/A gamedev.net 上有这个(旧(答案:
MSDN,请尽量避免使用这些指针,因为您要将指针投射到无符号的长整型中。这可能在 32 位可执行文件上正常工作,但如果以 64 位编译,则可能会遇到问题。
这支持了我的怀疑。
根据 MS 文档 SetWindowLongPtrW 函数,签名为:
LONG_PTR SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong );
所以,这应该可以解决它:
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(pDemoApp)
);
请注意关于LONG_PTR
的MS文档:
LONG_PTR
用于指针精度的有符号长整型类型。在将指针转换为 long 以执行指针算术时使用。
此类型在 BaseTsd.h 中声明如下:
C++
#if defined(_WIN64) typedef __int64 LONG_PTR; #else typedef long LONG_PTR; #endif
顺便说一句。我也没那么明白
DemoApp* pDemoApp = reinterpret_cast<DemoApp*>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
根据文档GetWindowLongPtrW函数,该函数返回LONG_PTR
。那么,为什么要static_cast<LONG_PTR>
呢?如果绝对必要,类型转换应始终是最后的手段。(虽然,我承认WinAPI可能没有它就无法使用。
- 使用 EvtSetChannelConfigProperty() 函数时出现访问冲突错误
- cv::resize() 失败并出现访问冲突错误(由 NULL> 处的 <struct 引起)
- 将 std::string 作为参数从一个 DLL 传递到另一个 DLL 引发访问冲突错误
- 遵循官方 Direct2D 示例,但出现访问冲突错误
- C++ 抛出读取访问冲突错误,但我不确定为什么。平铺滑块益智游戏
- 为什么我的顶点缓冲区对象出现访问冲突错误?
- 销毁 Box2D 主体 - 读取访问冲突错误
- 编译哈希算法时出现内存访问冲突错误
- 使用glCreateBuffers时发生访问冲突错误
- 访问冲突错误在 (而 (info[x] != ))
- 反转字符串 c++ 时出现访问冲突错误
- 我无法弄清楚此访问冲突错误.有人可以在这里帮助我吗?
- 使用内存访问冲突错误
- 读取字符串的字符时出错-访问冲突错误C++
- 创建链接列表时发生访问冲突错误
- 调试优先级队列程序时出现访问冲突错误
- C++LinkedList错误:访问冲突错误
- 为什么我在用SDL2_ttf填充文本时出现访问冲突错误
- MFC:在工作线程中使用对象的成员函数时获取访问冲突错误
- 在C++中使用Box2D物理退出游戏时出现访问冲突错误