7

我制作了一个示例来检查在 Windows 控制台应用程序中按下 Ctrl+C 时会发生什么:

bool    TerminationFlag=true;

int main()
{
    g_hTerminateEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    ::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
    while(1)
    {
        if(TerminationFlag == false)
        {
            break;
        }
    }
    return 0;
}

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{

    if (dwCtrlType == CTRL_C_EVENT ||
        dwCtrlType == CTRL_BREAK_EVENT ||
        dwCtrlType == CTRL_CLOSE_EVENT)
    {
        TerminationFlag=false;
        ::SetEvent(g_hTerminateEvent);
        return TRUE;
    }
    return FALSE;
}

当我按下 ctrl+c 时,我通过使用 Visual Studio 中的启动调试选项运行代码来测试代码我收到以下消息

0x7c87647d 处的第一次机会异常

当我按下继续选项时,TerminationFlag=false;即使我在控制处理程序中处理了 Ctrl+C,我的代码也会出现。你能告诉我有什么问题吗?

4

2 回答 2

14

我假设您从问题描述中使用 Microsoft Visual Studio。引发的第一个机会异常是由调试环境捕获的 CTRL-C 事件。这是预期的行为。

您可以选择忽略这一点:转到 Debug 菜单/Exceptions/Win32 Exceptions 并从“Thrown”列菜单中取出 CONTROL-C 检查。这将确保调试器仅在用户未处理时才在 CONTROL-C 上中断。见下图:

在此处输入图像描述

顺便说一句,您应该等待终止事件而不是轮询标志。你可能想要这样的东西:

#include "windows.h"
#include <iostream>
HANDLE g_hTerminateEvent;

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{

    if (dwCtrlType == CTRL_C_EVENT ||
        dwCtrlType == CTRL_BREAK_EVENT ||
        dwCtrlType == CTRL_CLOSE_EVENT)
    {
        std::cout << "Terminating" << std::endl;
        SetEvent(g_hTerminateEvent);

        return TRUE;
    }
    return FALSE;
}
int main()
{
    g_hTerminateEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);

    DWORD result = WaitForSingleObject(g_hTerminateEvent, INFINITE);
    return 0;
}
于 2012-11-03T07:57:13.190 回答
1

在调试器中运行这种东西时,你永远不会得到与没有调试器运行它相同的画面。在调试器中,您通常不能跳过使控制台输入/输出的系统功能。调试器将不可避免地与这里的系统交互。

最可靠的方法是追踪。

这可能无法直接回答问题。

ps 在您的代码示例中,现在不需要该事件。

来自 MSDN 的更新:

Value   Meaning
 0 CTRL_C_EVENT

从键盘输入或 GenerateConsoleCtrlEvent 函数生成的信号接收到 CTRL+C 信号。

于 2012-11-03T07:18:06.287 回答