处理线程时如何修复 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:
- 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();
我正在编写一个程序来检测按键并执行某些操作(在本例中,显示一个消息框)。
一切正常,除了当我尝试退出程序时,它显示了一个类似这个错误的弹出窗口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:
- 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();