异常处理C++

异常处理C++,c++,linux,windows,C++,Linux,Windows,我从Windows/Linux控制台接收输入,这样用户输入的密码在几乎所有Linux操作系统中都是隐藏的。 我应该如何优雅地处理以下代码段引发的异常 #ifdef _WIN32 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(hStdin, &mode); SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT)); std:

我从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);

<> P>以及上面的片段可能会抛出不同类型的异常,还有其他与平台无关的方法吗?在异常情况下,

< P>回滚操作通常是通过在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实现是类似的,相应的系统调用和成员进行了适当的调整。

您发布的代码不会抛出任何异常。@el.pescado:getlinecin,sTempPass;调用。由于调整输出字符串缓冲区的大小,这至少会引发std::bad_alloc异常。代码可能引发异常。@IInspectable您是对的。可以处理hStdin=GetStdHandleSTD\u INPUT\u HANDLE;如果句柄未返回,是否引发异常@Ilnspectable@Milind:Windows API作为C接口公开。错误仅通过返回值报告。在这种情况下,如果失败,它将返回无效的\u句柄\u值或NULL。即使它确实抛出了一个异常,这也无关紧要,因为该调用是在更改全局状态之前发出的