【问题标题】:How to fix Debug Error from Microsoft Visual C++ Runtime library when dealing with threads?处理线程时如何修复 Microsoft Visual C++ 运行时库中的调试错误?
【发布时间】:2021-12-20 03:18:33
【问题描述】:

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

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

现在,这个窗口不会弄乱我的程序中的任何东西,所以我可以把它留在那里,但它很烦人。

这是一个最小可重现示例,我刚开始在 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;
}

【问题讨论】:

标签: c++ winapi


【解决方案1】:

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

std::terminate 当程序由于以下任何原因无法继续时由 C++ 运行时调用:

  1. 可连接的 std::thread 被销毁或分配给

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

默认的 std::terminate_handler 调用 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();

【讨论】:

  • 回复:“你必须分离或加入td”——是的,其中任何一个都可以治疗症状,但detach 几乎总是错误的答案。 +1。
猜你喜欢
  • 1970-01-01
  • 2012-11-25
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
相关资源
最近更新 更多