Im writing a program that will detect a key press and do something (in this case show a message box), it all work fine when i try to exit the program it show a popup like this error window. Now this window doesnt mess up anything in my program so i could leave it there but it is annoying. Heres a Minimal Reproducible Sample, im just beginning to code in win32 so please don't criticize my inefficent code
#include <Windows.h>
#include <thread>
#include <chrono>
#define HFFFA 1001
#define MAINWINDOWSTYLE WS_OVERLAPPED| WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
std::chrono::milliseconds THREAD_WAIT(50);
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_COMMAND:
{
switch (wp)
{
case HFFFA:
{
MessageBox(hwnd, L"Sucess", L"Success", MB_OK);
break;
}
break;
}
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW));
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
void GetKeyPress(HWND hwnd)
{
int keypressed = -1;
while (TRUE)
{
if (GetAsyncKeyState(VK_F6))
{
SendMessage(hwnd, WM_COMMAND, (WPARAM)HFFFA, TRUE);
}
std::this_thread::sleep_for(THREAD_WAIT);
}
}
int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE hiprevinst, PWSTR nCmdLine, int ncmdshow)
{
const wchar_t CLASS_NAME[] = L"Axom";
WNDCLASS wc = { };
wc.lpfnWndProc = WndProc;
wc.hInstance = hinst;
wc.lpszClassName = CLASS_NAME;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Axom", MAINWINDOWSTYLE, CW_USEDEFAULT, CW_USEDEFAULT, 592, 600, NULL, NULL, hinst, NULL);
ShowWindow(hwnd, ncmdshow);
std::thread td(GetKeyPress, hwnd);
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
CodePudding user response:
When the events loop ends all wWinMain
local variables are destroyed. One of them is td
as your thread. When std::thread
is destroyed while it is in joinable state, std::terminate
is called:
std::terminate is called by the C runtime when the program cannot continue for any of the following reasons:
- a joinable std::thread is destroyed or assigned to
The default std::terminate
behaviour is to invoke std::abort
function.
The default std::terminate_handler calls std::abort.
You have to detach or join td
thread before it is destroyed. If you join the thread, you have to add some mechanism (for example via global flag variable) to inform GetKeyPress
thread function when to leave.
std::atomic_bool stopFlag; // global variable
void GetKeyPress(HWND hwnd) {
int keypressed = -1;
while (!stopFlag) {
if (GetAsyncKeyState(VK_F6))
SendMessage(hwnd, WM_COMMAND, (WPARAM)HFFFA, TRUE);
std::this_thread::sleep_for(THREAD_WAIT);
}
}
std::thread td(GetKeyPress, hwnd);
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
stopFlag = true;
td.join();