Problème de catch d'exception

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjours à tous,

j'étais en train de tester les exceptions des streams en c++, j'ai donc écris ce code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <climits>
#include "person.h"

void cin_state();

int main()
{
    std::cin.exceptions(std::ios::failbit);
    int x;

    cin_state();
    try
    {
    std::cin >> x;
    }
    catch (std::ios_base::failure const &problem)
    {
    cin_state();
    std::cout << problem.what() << std::endl;
    std::cin.clear();
    cin_state();
    std::cin.ignore(INT_MAX, '\n');
    }

    std::cout << x << std::endl;
    cin_state();

    return 0;
}

void cin_state()
{
    std::cout << "good  : " << std::cin.good() << std::endl;
    std::cout << "eof   : " << std::cin.eof() << std::endl;
    std::cout << "fail  : " << std::cin.fail() << std::endl;
    std::cout << "bad   : " << std::cin.bad() << std::endl;
    std::cout << "state : " << std::cin.rdstate() << std::endl;
}

mais le block try n'attrape pas l'exception et le programme me sort ça

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# ludovic at Tardis in ~workspace/C++/bordel [20:21:21]
$ ./executable 
good  : 1
eof   : 0
fail  : 0
bad   : 0
state : 0
ao
terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear
[1]    8837 abort (core dumped)  ./executable

Si vous pourriez m'expliquer pourquoi ça ne fonctionne pas cela me sera d'une grande aide.

Merci d'avance pour vos réponces :)

Édité par LudoBike

« La Nature est un livre écrit en langage mathématique », Galilée

+0 -0

Cette réponse a aidé l'auteur du sujet

Salut, c'est std::istream::clear() qui a lancé une exception dans ton catch() :p .

Ilearn32

Non, sinon le premier appel à cin_state dans le bloc catch (qui se trouve avant le clear) aurait affiché du texte juste après la saisie.

C'est un comportement assez étrange, et je ne saurai te dire la cause, d'après la doc ça a l'air correct. Visiblement, il suffit d'attraper une instance de std::exception plutôt qu'autre chose :

13
14
15
16
17
18
19
try
{
    std::cin >> x;
}
catch (std::exception const &problem)
{
    // ...
+0 -0

Visiblement, il suffit d'attraper une instance de std::exception plutôt qu'autre chose :

Olybri

Ben bonjour la sélectivité …

@LudoBike : je viens d'exécuter ton code en debug sur VS, je n'ai aucun soucis. Que dis ton debugger ?

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+1 -0

Cette réponse a aidé l'auteur du sujet

Ok, ça pue grave du cul. Cela ressemble à un bug crade dans g++ :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <typeinfo>
#include <iostream>
#include <climits>

void cin_state();

int main()
{
    std::cin.exceptions(std::ios::failbit);
    int x;
    try
    {
        std::cin >> x;
    }
    catch (std::exception const &problem)
    {
        std::cout << typeid(std::ios_base::failure).name() << std::endl;
        std::cout << typeid(problem).name() << std::endl;
        std::cout << problem.what() << std::endl;
    }

    return 0;
}

void cin_state()
{
    std::cout << "good  : " << std::cin.good() << std::endl;
    std::cout << "eof   : " << std::cin.eof() << std::endl;
    std::cout << "fail  : " << std::cin.fail() << std::endl;
    std::cout << "bad   : " << std::cin.bad() << std::endl;
    std::cout << "state : " << std::cin.rdstate() << std::endl;
}

Résultat :

1
2
3
NSt8ios_base7failureB5cxx11E
NSt8ios_base7failureE
basic_ios::clear

On dirait que les namespaces ont craqué leur slip.

BINGO : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+4 -0

@Ludo Bike: J'ai testé ton code avec Code::Blocks et j'ai la même chose que toi, finalement. Puis la doc dit ça:

if an exception is thrown, the object is in a valid state. It throws an exception of member type failure if the resulting error state flag is not goodbit and member exceptions was set to throw for that state. Any exception thrown by an internal operation is caught and handled by the function, setting badbit. If badbit was set on the last call to exceptions, the function rethrows the caught exception.

D'après ce que j'ai compris,comme tu as réglé au départ le comportement de std::cin en cas d'exception, les fonctions relancent l'exception(pas sûr, quoi qu'il en soit, il faut vraiment que je révise mon anglais :( ).

Où c'est vraiment un bug de g++, ou c'est le compilateur de Visual Studio qui ne respecte pas les normes :p .

PS : testé avec code::blocks compilateur 5.2 avec l'option -std=c++14 :p .

PS2 : Bravo Ksass `Peuk pour avoir trouvé la solution :) .

Édité par Ilearn32

+0 -0

Où c'est vraiment un bug de g++, ou c'est le compilateur de Visual Studio qui ne respecte pas les normes :p .

PS : testé avec code::blocks compilateur 5.2 avec l'option -std=c++14 :p .

Ilearn32

  • Testé avec GCC 5.3 : crash.
  • Testé avec GCC 6.0 : crash.
  • Testé avec clang 3.7 : fonctionne.

Donc je pense bien que ce soit un bug de GCC.

+0 -0

C'est une régression en fait. Voir le lien que j'ai mis plus haut, la 4.9 fonctionnait, ce n'est plus le cas à partir de la 5.1.

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+1 -0
Auteur du sujet

Ok donc du coup il y a un problème avec gcc qui fait que l'exception doit etre catch comme étant une std::exeption alors que c'est une std::ios_base::exeption.

J'espère qu'il vont le corriger dans une prochaine version, en tous cas merci de vos réponces :)

« La Nature est un livre écrit en langage mathématique », Galilée

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte