My project is C++ Windows Desktop Wizard AKA Win32 API project.
In function WinMain(...) I'm creating my window:
hWnd = CreateWindowEx(NULL, _T("DesktopApp"), _T("Hi, I'm window"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
And after that for some reason my window has status "unable to read memory" (therefore I can't create GUIs without this issue). I checked even 2nd page of Google to find a resolve of this problem. Microsoft's documentation didn't help: I checked the implementation and it fits with mine. I can't fix it for a long time, mb I'm blind and I wrote smth wrong before, despite I've created 2 working projects before (comparison didn't give any results).
Here goes the whole code:
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <shellapi.h>
#include <ctime>
HWND hWnd;
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
hInst = hInstance;
hWnd = CreateWindowEx(NULL, _T("DesktopApp"), _T("Hi, I'm window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Thanks in advance for help.
When STRICT Type Checking
is enabled during compiling, HWND
is a typedef for HWND__*
, where HWND__
is a struct with an unused
data member (only because a struct
can't legally be empty in C, but it can in C++), eg:
winnt.h:
#ifdef STRICT
typedef void *HANDLE;
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
windef:
DECLARE_HANDLE (HWND);
So, when STRICT
is defined, HWND
is an alias for struct HWND__*
, otherwise it is an alias for PVOID
( void*
). Same with MANY other handle types ( HHOOK
, HEVENT
, HGDIOBJ
, HBITMAP
, etc).
For your debugger to be showing you the unused
member when viewing an HWND
, that means you are compiling with STRICT
defined (which is a good thing, you should be). The debugger sees a pointer to a type, and tries to display the data that type contains.
However, an HWND
is not REALLY a pointer to a struct HWND__
in memory. It is actually just an opaque value provided by the kernel. What an HWND
actually refers to is private to the kernel, a user-mode debugger has no way of knowing what that really is.
STRICT
handling is merely provided for compile-time type safety, so that user code can't accidentally pass other handle types where an HWND
is expected, and vice versa.
In your case, your HWND
has a value of 0x00170344
, which means CreateWindowEx()
is not failing, the HWND
itself is valid. But 0x00170344
is not a valid memory address in your app's address space, so when the debugger tries to access the unused
member at that address, it fails with "unable to read memory". The unused
member will NEVER be valid in a user-mode debugger (that is why it is "unused"). The only thing that is important is whether the value of the HWND
itself is 0
or not.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.