C++. I'm getting Access Violation on CreateWindow with a getter to retreive the classname string

0

(error 'codes' copied and pasted at the bottom)

I am following an online tutorial, but also have 3 books and finished an advanced c++ course by microsoft @ edX, but realise I'm still a beginner. I mention this so people don't think I'm learning primarily by poor youtube tutorials, I'm not.

This error is from within a c++ Window Class 'Window' that I've created which holds another class, 'Windowclass'. They are used to create windows and the inner singleton class hides the details.

I'll copy the code I think is relevant from the constructor.

It seems the problem may be in the window constructor @ hWnd = CreateWindow(Here, name, etc, etc:

Window::Window(int width, int height, const char* name) noexcept

{
    RECT wr;
    wr.left = 100;
    wr.right = width + wr.left;
    wr.top = 100;
    wr.bottom = height + wr.top;
    AdjustWindowRect(&wr, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, false);
    //create window & get hWnd
    hWnd = CreateWindow(WindowClass::GetName(), name, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | CW_USEDEFAULT | CW_USEDEFAULT, wr.right, wr.left, wr.bottom, wr.top, nullptr, nullptr, WindowClass::GetInstance(), this);

    ShowWindow(hWnd, SW_SHOWDEFAULT);
}

If I change the first argument from the CreateWindow to what I think is called a string literal, i.e. "Window" instead of the GetName() getter then the program seems to run fine.

here is the code of the getter, please note the getter seems to work fine elsewhere. For instance, when it is being called in the creation of the window classname

wc.lpszClassName = GetName();

Getter:

const char* Window::WindowClass::GetName() noexcept {

    return wndClassName;
}

whilst I don't want to copy too much code, below is the WindowClass which sits within its parent class, 'Window'.

Please also note, my mental health is not great, and coding really helps (with much rest in between) with my mental health recovery, arguments and insults don't. But happy to take constructive feedback.

class WindowClass
{
public:
    static const char* GetName() noexcept;
    static HINSTANCE GetInstance() noexcept;

private:
    WindowClass() noexcept;
    ~WindowClass();
    WindowClass(const WindowClass&) = delete;
    WindowClass& operator=(const WindowClass&) = delete;
    static constexpr const char* wndClassName = "Ryan Direct3d";
    static WindowClass wndClass;
    HINSTANCE hInst;
};

I appreciate all feedback on this that is relevant. Why am I getting: Exception thrown at 0x00000000 in WindowsApp1.exe: 0xC0000005: Access violation executing location 0x00000000. Unhandled exception at 0x7155CCE0 in WindowsApp1.exe: 0xC000041D: An unhandled exception was encountered during a user callback.

Code to compile below this line


#include <Windows.h>
#include <string>

class Window
{
private:
    //singleton class - manages registration and cleanup / of window  class (unregistered)
    class WindowClass
    {
    public:
        static const char* GetName() noexcept;
        static HINSTANCE GetInstance() noexcept;

    private:
        WindowClass() noexcept;
        ~WindowClass();
        WindowClass(const WindowClass&) = delete;
        WindowClass& operator=(const WindowClass&) = delete;
        //wndClassName called by getter
        static constexpr const char* wndClassName = "Ryan";
        static WindowClass wndClass;
        HINSTANCE hInst;
    };
public:

    Window(int width, int height, const char* name) noexcept;
    ~Window();
    Window(const Window&) = delete;
    Window& operator= (const Window&) = delete;

private:
    int width = 0;
    int height = 0;
    HWND hWnd;
};


//Window Class stuff
Window::WindowClass Window::WindowClass::wndClass; //
Window::WindowClass::WindowClass() noexcept : hInst(GetModuleHandle(nullptr))
{

    WNDCLASSEX wc = { 0 };
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    //wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = GetInstance();
    wc.hIcon = nullptr;
    wc.hCursor = nullptr;
    wc.hbrBackground = nullptr;
    wc.lpszMenuName = nullptr;
    wc.lpszClassName = GetName();
    wc.hIconSm = nullptr;
    RegisterClassEx(&wc);

}


const char* Window::WindowClass::GetName() noexcept {

    return wndClassName;
}

HINSTANCE Window::WindowClass::GetInstance() noexcept {

    return wndClass.hInst;

}
Window::WindowClass::~WindowClass()
{
    UnregisterClass(wndClassName, GetInstance());
}


//Window Creation
Window::Window(int width, int height, const char* name) noexcept
{
    RECT wr;
    wr.left = 100;
    wr.right = width + wr.left;
    wr.top = 100;
    wr.bottom = height + wr.top;
    AdjustWindowRect(&wr, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, false);
    //create window & get hWnd
    hWnd = CreateWindow("Ryan", name, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | CW_USEDEFAULT | CW_USEDEFAULT, wr.right, wr.left, wr.bottom, wr.top, nullptr, nullptr, WindowClass::GetInstance(), nullptr);
        ShowWindow(hWnd, SW_SHOW);
}


Window::~Window() {

    DestroyWindow(hWnd);
}



//wndprocs
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch (msg) //use a switch because in future we will add / process many kinds of messages
    {
    case WM_KEYUP:
        if (wParam == 'F')
        {
            SetWindowText(hWnd, "Dogmah");
        }
        break;

    case WM_CLOSE:
        PostQuitMessage(69);
        break;
    case WM_KEYDOWN:
        if (wParam == 'F')
        {
            SetWindowText(hWnd, "New Name");
        }
        break;
    case WM_CHAR:
    {
        static std::string title;
        title.push_back((char)wParam);
        SetWindowText(hWnd, title.c_str());
    }
    case WM_LBUTTONDOWN:
    {

    }

    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

int CALLBACK WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR   lpCmdLine,
    int nCmdShow)
{

    Window Ryan(600, 500, "Hey");


    //message pump
    MSG msg;
    BOOL gResult;
    //register custom class for outputting EXTRA msg details

    while ((gResult = GetMessage(&msg, nullptr, 0, 0)) > 0)
    {
        TranslateMessage(&msg);

        DispatchMessage(&msg);
    }

    if (gResult == -1) { return -1; }

    else { return msg.wParam; }

    return 0;
}
c++
callback
access
hwnd
createwindow
asked on Stack Overflow Mar 19, 2020 by Ryan Birks • edited Mar 19, 2020 by Ryan Birks

1 Answer

0

You commented out the WndProc assignment in the WNDCLASSEX:

Window::WindowClass::WindowClass() noexcept : hInst(GetModuleHandle(nullptr))
{

    WNDCLASSEX wc = { 0 };
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    //wc.lpfnWndProc = WndProc;
    ...

To fix, simply forward declare your WndProc function (which is defined below). And uncomment.

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

//Window Class stuff
Window::WindowClass Window::WindowClass::wndClass; //
Window::WindowClass::WindowClass() noexcept : hInst(GetModuleHandle(nullptr))
{

    WNDCLASSEX wc = { 0 };
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = WndProc;
    ...

After I made that change, the crash goes away and your window shows up:

enter image description here

answered on Stack Overflow Mar 19, 2020 by selbie

User contributions licensed under CC BY-SA 3.0