You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Windows CMD中运行程序时调整窗口大小致异常的解决问询

解决Windows CMD调整窗口尺寸导致C++程序异常/无限循环的问题

问题原因

Windows控制台在调整窗口大小或缓冲区尺寸时,会向关联进程发送WINDOW_BUFFER_SIZE_EVENT控制台事件。默认情况下,标准输入流std::cin会被该事件中断,导致std::cin.get()、getline()等输入函数返回失败(或触发EOF状态)。如果代码未处理这种错误状态,循环逻辑会反复执行,最终陷入无限循环。


解决方案1:注册控制台事件处理函数,忽略窗口尺寸变化事件

通过Windows API注册自定义控制台事件处理函数,过滤掉窗口尺寸变化事件,避免其干扰输入逻辑。同时在循环中处理std::cin的错误状态,确保输入流程正常恢复。

#include <iostream>
#include <windows.h>
#include <limits>  // 用于std::numeric_limits

// 自定义控制台事件处理函数
BOOL WINAPI ConsoleHandler(DWORD dwCtrlType) {
    if (dwCtrlType == WINDOW_BUFFER_SIZE_EVENT) {
        // 忽略窗口尺寸/缓冲区变化事件,返回TRUE表示已处理
        return TRUE;
    }
    // 其他事件(如Ctrl+C)按系统默认逻辑处理
    return FALSE;
}

int main() {
    // 注册事件处理函数
    if (!SetConsoleCtrlHandler(ConsoleHandler, TRUE)) {
        std::cerr << "注册控制台事件处理器失败,错误码: " << GetLastError() << std::endl;
        return 1;
    }

    int i = 0;
    std::cout << "WHY!" << std::endl;

    do {
        // 清除之前可能触发的输入错误状态
        if (!std::cin) {
            std::cin.clear();
            // 忽略缓冲区中残留的无效数据
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        std::cin.get();
        std::cout << "This is working now\n";
        ++i;
    } while (i < 10);

    return 0;
}

解决方案2:使用Windows原生输入函数ReadConsole

改用Windows API提供的ReadConsole函数读取输入,该函数不会被窗口尺寸变化事件中断,能稳定处理控制台输入。缺点是代码会绑定Windows平台,失去跨平台兼容性。

#include <iostream>
#include <windows.h>

int main() {
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE) {
        std::cerr << "获取标准输入句柄失败,错误码: " << GetLastError() << std::endl;
        return 1;
    }

    int i = 0;
    std::cout << "WHY!" << std::endl;

    do {
        wchar_t inputChar;
        DWORD charsRead;
        // 读取单个字符,不受窗口调整事件干扰
        if (ReadConsole(hStdin, &inputChar, 1, &charsRead, NULL)) {
            std::cout << "This is working now\n";
            ++i;
        } else {
            std::cerr << "读取输入失败,错误码: " << GetLastError() << std::endl;
            break;
        }
    } while (i < 10);

    return 0;
}

注意事项

  • 若使用CLion运行程序,需确保配置为在原生Windows CMD窗口中启动(而非CLion内置终端),两种方案才能正常生效。
  • 方案1中,std::numeric_limits需要包含<limits>头文件,否则会编译报错。

内容的提问来源于stack exchange,提问作者Nuno Domingues

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:31:05