异常处理 C++
Posted
技术标签:
【中文标题】异常处理 C++【英文标题】:Exception Handling C++ 【发布时间】:2017-02-06 10:15:46 【问题描述】:我从 Windows/Linux 控制台接收输入,以便用户键入的密码保持隐藏状态,因为它在几乎所有 Linux 操作系统中都会发生。 下面sn-p抛出的异常应该如何优雅的处理?
#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);
上面的 sn-p 可能抛出不同类型的异常的可能场景是什么?还有其他独立于平台的方法吗?
【问题讨论】:
您发布的代码不会抛出任何异常。 @el.pescado:有一个getline(cin, sTempPass);
调用。由于调整输出字符串缓冲区的大小,这至少会引发std::bad_alloc
异常。代码可以抛出异常。
@IInspectable 你是对的。
【参考方案1】:
异常情况下所需的回滚操作通常通过在 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 实现是类似的,相应的系统调用和成员进行了适当调整。
【讨论】:
可以处理 hStdin = GetStdHandle(STD_INPUT_HANDLE);如果不返回句柄,则抛出异常? @Ilnspectable @Milind:Windows API 公开为 C 接口。错误仅通过返回值报告。在这种情况下,如果GetStdHandle 失败,则返回INVALID_HANDLE_VALUE
(或NULL
)。即使它确实抛出了异常也没关系,因为调用是在更改全局状态之前进行的。
有道理,谢谢 (Y)以上是关于异常处理 C++的主要内容,如果未能解决你的问题,请参考以下文章