2017-02-06 27 views
0

ほとんどすべてのLinuxオペレーティングシステムで発生するように、ユーザータイプが隠されたままになるように、Windows/Linuxコンソールから入力を受け取ります。 次のスニペットによってスローされた例外を正常に処理するにはどうすればよいですか?例外処理C++

#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); 

上記のスニペットでは、さまざまなタイプの例外が発生する可能性があります。これを行うためのプラットフォームに依存しない方法がありますか?

+0

投稿したコードは例外をスローしません。 –

+1

@ el.pescado: 'getline(cin、sTempPass);'呼び出しがあります。少なくともこれは、出力文字列バッファのサイズ変更のために 'std :: bad_alloc'例外を発生させる可能性があります。コード*は例外をスローすることができます。 – IInspectable

+0

@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の実装は、それぞれのシステムコールとメンバーが適切に調整されている点で似ています。

+0

hStdin = GetStdHandle(STD_INPUT_HANDLE)を処理できます。ハンドルが返されない場合は例外をスローしますか? @Ilnspectable –

+0

@Milind:Windows APIはCインターフェイスとして公開されています。エラーは戻り値のみによって報告されます。この場合、[GetStdHandle](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx)に失敗すると、 'INVALID_HANDLE_VALUE'(または' NULL')を返します。たとえそれが例外をスローしたとしても、グローバルな状態を変更する前に呼び出しが行われるため、問題はありません。 – IInspectable

+0

感謝、感謝(Y) –