异常处理C++

Exception Handling C++

本文关键字:C++ 异常处理      更新时间:2023-10-16

我正在从Windows/Linux控制台接管输入,以便用户键入的密码保持隐藏状态,因为它在几乎所有Linux操作系统中都会发生。我应该如何优雅地处理以下代码片段引发的异常?

#ifdef _WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
GetConsoleMode(hStdin, &mode);
SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
std::string sTempPass;
getline(cin, sTempPass);
SetConsoleMode(hStdin, mode);
#elif __linux__
termios oldt;
tcgetattr(STDIN_FILENO, &oldt);
termios newt = oldt;
newt.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
std::string sTempPass;
getline(cin, sTempPass);
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);

上面的代码片段可能会引发不同类型的异常,是否有任何其他独立于平台的方法可以做到这一点?

发生异常时所需的回滚操作通常通过在 C++ 中运行析构函数来实现。在这种情况下,您可以创建一个存储当前状态的类,并在其析构函数中还原它:

struct ConsoleMode {
    DWORD mode;
    HANDLE handle;
    ConsoleMode(const HANDLE h) : handle(h) {
        ::GetConsoleMode(handle, &mode);
    }
    ~ConsoleMode() {
        ::SetConsoleMode(handle, mode);
    }
}

然后,调用代码只是构造一个具有自动存储持续时间的对象,并将清理留给自动堆栈展开:

HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
{
    ConsoleMode savedState(hStdin);
    ::SetConsoleMode(hStdin, savedState.mode & (~ENABLE_ECHO_INPUT));
    std::string sTempPass;
    getline(cin, sTempPass);
   // savedState goes out of scope and runs its destructor to restore state.
   // The destructor runs as part of stack unwinding in case of an exception as well.
}

Linux 实现是类似的,相应地调整了相应的系统调用和成员。