Running a thread alongside win32

I'm trying to run an SFML window at the same time as my simple win32 application. The idea is to have a win32 window taking input from the user and then SFML will generate an image from that input. The windows seem to function just fine together but as soon as I close one of them it crashes trying to access deleted memory (exception at: 0xDDDDDDDD, 0xC0000005). The problem started when I added an std::thread that simply polls events for the SFML window, all it really does is check if the user has hit the "X" (close button) on the window and then calls close() on the SFML window object. It seems to crash when the thread exits even if the thread runs an empty function (does nothing). I tried creating a thread using this tutorial: https://www.bogotobogo.com/cplusplus/multithreaded2.php, but it doesn't work either although I got it to not crash only because the thread dies before it's done somehow (I guess win32 decides this for itself). Can anyone explain what is going on and how I am supposed to run a thread in a win32 application?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
…
sf::RenderWindow window_SFML(sf::VideoMode(1280, 720), "BST image");
std::mutex mtx;

// Thread class declared hereclass simpleThread : public Thread {
public:
    bool halt;
    simpleThread(int ID) : myID(ID), halt(false) {}
    virtual void* run() {
        /*sf::Event e;
        while (window_SFML.isOpen()) {
            mtx.lock();
            while (window_SFML.isOpen() && window_SFML.pollEvent(e)) {
                if (e.type == sf::Event::Closed)
                    window_SFML.close();
            }
            mtx.unlock();
        }*/
        std::wstring tmp = L"Thread " + std::to_wstring(myID) + L" running\n";
        OutputDebugString((LPCWSTR)(tmp.c_str()));

        std::condition_variable cv;
        std::unique_lock<std::mutex> lk(mtx);
        cv.wait(lk, [this] { return halt; });
        // thread dies before this line

        tmp = L"Thread " + std::to_wstring(myID) + L" exiting\n";
        OutputDebugString((LPCWSTR)(tmp.c_str()));
        return reinterpret_cast<void*>(myID);
    }
private:
    int myID;
};
…
simpleThread sfml_loop(0);
//std::thread sfml_loop;int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here. ?

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_BINARYTREEVISUALIZER, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BINARYTREEVISUALIZER));

    MSG msg;

    /// RUNTIME ERROR: when the thread dies the program crashes
    /*sfml_loop = std::thread([]() {
        sf::Event e;
        while (window_SFML.isOpen()) {
            mtx.lock();
            while (window_SFML.isOpen() && window_SFML.pollEvent(e)) {
                if (e.type == sf::Event::Closed)
                    window_SFML.close();
            }
            mtx.unlock();
        }
    });*/
    sfml_loop.start();

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}
…
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    …
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        …
        case IDM_EXIT:
            sfml_loop.halt = true;
            sfml_loop.join();
            DestroyWindow(hWnd);
            /*mtx.lock();
            if (window_SFML.isOpen()) window_SFML.close();
            mtx.unlock();*/
            //if (sfml_loop.joinable()) sfml_loop.join();
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
        break;
    …
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
    …
}
Last edited on
The idea is to have a win32 window taking input from the user and then SFML will generate an image from that input.
Does all this need to be done in a monolithic app?
I'll throw my two cents in although I am unfamililar with SMFL. I clicked the link you referenced and was surprised there was an entire class dedicated to threads but never makes use of the Windows API's very nice and simple CreateThread() function.

Here's untested example code for you:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <windows.h>

DWORD WINAPI MyThread(LPVOID lpParam)
{
      while(1) //to keep the thread running
      {
           //execute your code
           //Sleep(1) //needed only if this thread is not very CPU-consuming, it will become so if it's too simple
      }
      return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmd, int nCmdShow) //I use int, sue me
{
          while(1)
         {
                CreateThread( NULL, 0, MyThread, NULL, 0, NULL);
                /* The rest of your program */
                if(GetKeyState(VK_ESCAPE) & 0x80) PostQuitMessage(0);
         }
         return 1337;
}


And that's it, hope that gives you a bit of help. Or perhaps you already knew this -- that tutorial, to me at least, is way too complex to show someone who is new to the Windows API on how to handle threads.


~TomTheFox/Xterria from cprogramming.com
The most basic Windows applications start with a single thread. The function call we use to create a child thread is CreateThread().
https://www.talktowendys.org/
Registered users can post here. Sign in or register to post.