2017-02-06 1 views
0

Je prends l'entrée de la console Windows/Linux de telle sorte que le mot de passe que les types d'utilisateur restent caché comme cela se produit dans presque tous les systèmes d'exploitation Linux. Comment dois-je gérer avec élégance l'exception renvoyée par l'extrait suivant?Gestion des exceptions 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); 

Et quels sont les scénarios possibles l'extrait ci-dessus peut lancer différents types d'exception et est-il une autre plate-forme de manière indépendante pour le faire?

+0

Le code que vous avez posté ne comporte aucune exception. –

+1

@ el.pescado: Il y a une invocation 'getline (cin, sTempPass); À tout le moins, cela peut déclencher une exception 'std :: bad_alloc' en raison du redimensionnement du tampon de chaîne de sortie. Le code * peut * jeter des exceptions. – IInspectable

+0

@IInspectable vous avez raison. –

Répondre

1

Les opérations de restauration requises en cas d'exceptions sont généralement implémentées au moyen de l'exécution d'un destructeur en C++. Dans votre cas, vous pouvez créer une classe qui stocke l'état actuel, et il rétablit dans son destructor:

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

Le code d'appel puis construit simplement un objet avec une durée de stockage automatique, et laisse le nettoyage à pile automatique de déroulement:

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. 
} 

L'implémentation de Linux est analogue, avec les appels système et les membres respectifs correctement ajustés.

+0

Can HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE); jeter une exception si dans le cas où le handle n'est pas retourné? @Ilnspectable –

+0

@Milind: L'API Windows est exposée en tant qu'interface C. Les erreurs sont signalées uniquement par les valeurs de retour. Dans ce cas, si [GetStdHandle] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx) échoue, il renvoie INVALID_HANDLE_VALUE' (ou 'NULL'). Même s'il y avait une exception, cela n'aurait pas d'importance, puisque l'appel est fait avant de changer l'état global. – IInspectable

+0

Donne un sens, merci (Y) –