处理线程时如何修复 Microsoft Visual C++ Runtime 库的调试错误?

How to fix Debug Error from Microsoft Visual C++ Runtime library when dealing with threads?

我正在编写一个程序来检测按键并执行某些操作(在本例中,显示一个消息框)。

一切正常,除了当我尝试退出程序时,它显示了一个类似这个错误的弹出窗口window:

现在,这个 window 不会弄乱我的程序,所以我可以把它留在那里,但它很烦人。

这是一个最小的可重现示例,我刚刚开始在 Win32 中编写代码,所以请不要批评我的低效代码。

#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;
}

当事件循环结束时,wWinMain的所有局部变量都被销毁。其中之一是 td 作为您的话题。当std::thread处于可连接状态时被销毁,std::terminate()被调用:

std::terminate is called by the C++ runtime when the program cannot continue for any of the following reasons:

  1. a joinable std::thread is destroyed or assigned to

默认 std::terminate() 行为是调用 std::abort() 函数。

The default std::terminate_handler calls std::abort.

您必须在 td 线程上调用 detach()join() 才能销毁它。如果加入线程,则必须添加一些机制(例如,通过全局标志变量)来通知 GetKeyPress 线程函数何时离开。

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();