27 votes

Des outils pour générer des messages d'erreur de meilleure qualité pour le code basé sur un modèle?

Concepts, qui rendraient ces outils inutiles, sont pas partie de C++11.

  • STLFilt aurait été une option, mais il n'est plus maintenu.

  • Clang prétend donner expressive diagnostics bien que l'important C++11 caractéristiques ne sont pas encore disponibles.

  • colorgcc semble abandonné depuis 1999.

Ce qu'est la production d'outils de qualité sont disponibles à déchiffrer les messages d'erreur provenant de modèle à base de code? Eclipse-CDT de soutien serait sympa aussi. :)

Si je me rends sur le C++11, quelles options dois-je pour C++98?


Questions connexes:

14voto

Dietmar Kühl Points 70604

Nous allons avoir un coup de couteau à une réponse (j'ai marqué ce wiki de la communauté afin d'obtenir une bonne réponse de l'ensemble)...

Je travaille depuis longtemps avec des modèles et des messages d'erreur ont généralement améliorée d'une manière ou d'une autre:

  • L'écriture d'une pile d'erreurs crée beaucoup plus de texte, mais aussi inclut généralement le niveau de l'utilisateur est à la recherche à ce qui est généralement comprend une allusion à ce qui est le véritable problème. Étant donné que le compilateur ne voit qu'une unité de traduction jeté à elle, il n'y en a pas beaucoup qui peut être fait à la détermination de l'erreur dans la pile est la plus appropriée pour l'utilisateur.
  • En utilisant le concept de dames, c'est à dire des classes ou des fonctions dont l'exercice de tous les membres de modèle arguments et éventuellement générer des messages d'erreurs à l'aide de static_assert() donner l'auteur du modèle une façon d'informer les utilisateurs sur des hypothèses qui, apparemment, ne pas tenir.
  • Informer l'utilisateur sur les types, écrit-il, plutôt que d'élargir tous les typedefs que le compilateur comme pour voir au niveau le plus bas contribue également. clang est plutôt bon à ce jeu et en fait vous donne des messages d'erreur par exemple, parle de std::string plutôt que d'étendre les choses de type tout ce qu'il finit par être.

Une combinaison de la technique en cause par exemple clang pour créer assez décent message d'erreur (même si elle n'est pas mise en œuvre en C++2011, encore; cependant, aucun compilateur ne et pour autant que je peux dire à gcc et clang sont en tête du peloton). Je sais que d'autres les développeurs de compilateurs travailler activement sur l'amélioration du modèle de messages d'erreur que beaucoup de programmeurs ont découvert que les modèles sont en fait un énorme bond en avant, même si les messages d'erreur sont quelque chose qui prend un peu de temps pour s'y habituer.

Un problème d'outils comme stlfilt visage est que les compilateurs C++ et les bibliothèques sont en cours de développement. Il en résulte des messages d'erreur de décalage de tous les temps, de sorte que l'outil de recevoir des différentes sorties. Même s'il est bon que les rédacteurs du compilateur de travail sur l'amélioration des messages d'erreur, cela rend la vie plus difficile pour les gens qui essaient de travailler à partir des messages d'erreur qu'ils ont reçu. Il ya un autre côté, c'est ainsi: une fois un certain motif d'erreur est détecté est commune et est ramassé par exemple par stlfilt (ainsi, il n'est pas activement maintenu autant que je sache) les rédacteurs du compilateur sont probablement désireux de signaler les erreurs à la suite de ces modèles directement, peut-être également fournir des informations supplémentaires à la disposition du compilateur mais non émis avant. Autrement dit, je m'attends à ce que les rédacteurs du compilateur sont très réceptifs aux rapports des utilisateurs décrivant les situations d'erreur courants et la façon dont ils sont meilleurs rapporté. Les rédacteurs du compilateur peut ne pas voir les erreurs elles-mêmes parce que le code est en fait C (par exemple gcc est implémenté en C) ou parce qu'ils sont tellement habitués à un certain nombre de modèles techniques d'éviter certaines erreurs (par exemple, l'omission de l' typename pour les types de charge).

Enfin, pour répondre à la question sur les outils concrets: le principal "outil" que j'utilise quand je me sorte de coincé avec un compilateur se plaindre de certains instanciation d'un modèle est d'utiliser des compilateurs différents! Bien qu'il n'est pas toujours le cas, mais souvent un compilateur signale une incompréhensible messages d'erreur qui n'a de sens qu'après avoir vu le nombre assez concis rapport à partir d'un autre compilateur (dans le cas où vous êtes intéressé, j'utilise régulièrement une version récente de gcc, clang, et EDG pour cela). Je ne suis pas au courant de facilement emballé trop comme stlfilt, cependant.

6voto

AshleysBrain Points 11439

Je sais que cela peut ne pas être aussi utile que tu voulais, mais j'ai trouvé le meilleur outil contre le modèle de messages d'erreur est la connaissance.

Une bonne compréhension de la STL et comment l'utiliser, il vous permettra d'éviter beaucoup d'erreurs dans la première place. Deuxièmement, souvent des messages d'erreur des fonctions dans la STL source - si vous avez une idée comment le TSL est mis en œuvre, cela peut être extrêmement utile à déchiffrer ce que le message d'erreur est sur. Enfin, le compilateur décideurs sont conscients de ce problème et sont progressivement l'amélioration de message d'erreur de sortie, de sorte que vous ferait bien de s'en tenir à la version la plus récente de votre compilateur.

Voici un bon exemple d'une obscure modèle d'erreur:

std::vector<std::unique_ptr<int>> foo;
std::vector<std::unique_ptr<int>> bar = foo;

unique_ptr n'est pas copiable, elle ne peut être déplacée. Donc, essayez d'affecter un vecteur de unique_ptr à un autre vecteur signifie quelque part dans le vecteur de code source va essayer de copier un pointeur unique. Par conséquent l'erreur proviennent de code qui n'est pas le vôtre et jeter un assez opaque message d'erreur comme un résultat. L'idéal message d'erreur serait

main.cpp(20): ne peut pas construire de 'bar' de 'foo': foo type de modèle est non-copiable

Au lieu de cela, VS2010 donne l'erreur suivante:

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(48): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(197) : see reference to function template instantiation 'void std::_Construct<std::unique_ptr<_Ty>,const std::unique_ptr<_Ty>&>(_Ty1 *,_Ty2)' being compiled
1>          with
1>          [
1>              _Ty=int,
1>              _Ty1=std::unique_ptr<int>,
1>              _Ty2=const std::unique_ptr<int> &
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(196) : while compiling class template member function 'void std::allocator<_Ty>::construct(std::unique_ptr<int> *,const _Ty &)'
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(421) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>,
1>              _Alloc=std::allocator<std::unique_ptr<int>>
1>          ]
1>         main.cpp(19) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]

Le tamisage à travers cela, il y a des indices. La première section fait référence à un membre privé de l'accès de l' std::unique_ptr<int>. La deuxième section, si vous cliquez sur la ligne de source, points au le constructeur de copie d' unique_ptr, ce qui est déclarée sous un private: spécificateur. Alors maintenant, nous savons que nous avons essayé de copier un unique_ptr qui n'est pas autorisé. Les Sections 3, 4 et 5, juste au point de code réutilisable - c'est juste du bruit. L'article 6 dit: "voir la référence à la classe d'instanciation du modèle 'std::_Vector_val<_Ty,_Alloc>' cours de compilation". En d'autres termes, cette erreur s'est produite dans le vecteur de code de modèle. La dernière partie est la plus intéressante: il pointe directement à la ligne de déclarer foo dans votre propre code source, c'est compris où dans votre code source provient l'erreur de!

Donc, en additionnant les indices:

  • Il provient de foo,
  • Il provient de vecteur de code,
  • Il essaie de copier un unique_ptr qui n'est pas autorisé.
  • Conclusion: le vecteur essayé de copier l'un de ses éléments, ce qui n'est pas autorisé. Passer en revue le code pour foo et de vérifier quelque chose de provoquant une copie.

Puisque le compilateur seulement signaler au foo déclaration, si la cession est loin dans le code source de certains de chasse seront impliqués. Ce n'est évidemment pas l'idéal, mais je pense que cette approche en fin de compte vous donne plus de chance de corriger les erreurs en général. Vous allez commencer à reconnaître ce genre de vidage d'erreur signifie "vous avez copié un unique_ptr". Encore une fois, je ne suis pas à la défendre, il a certainement besoin de l'amélioration - mais je pense que de nos jours il y a juste assez d'informations dans la sortie combinée avec une bonne connaissance de la STL permet de résoudre le problème.

4voto

Reuben Morais Points 683

J'ai trouvé Clang pour générer les meilleurs messages d'erreur pour le code fortement basé sur des modèles. Bien sûr, la verbosité est inévitable dans la plupart des cas, mais elle est toujours meilleure que GCC ou MSVC la plupart du temps. Voici le message d'erreur Clang pour l'exemple de code publié par AshleysBrain:

 $ clang++ -std=c++11 -stdlib=libc++ -o dummy dummy.cpp 
In file included from dummy.cpp:1:
In file included from /usr/include/c++/v1/vector:243:
In file included from /usr/include/c++/v1/__bit_reference:15:
In file included from /usr/include/c++/v1/algorithm:594:
/usr/include/c++/v1/memory:1425:36: error: calling a private constructor of class 'std::__1::unique_ptr<int,
      std::__1::default_delete<int> >'
                ::new ((void*)__p) _Tp(_STD::forward<_Args>(__args)...);
                                   ^
/usr/include/c++/v1/memory:1358:14: note: in instantiation of function template specialization
      'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::__construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int,
      std::__1::default_delete<int> > &>' requested here
            {__construct(__has_construct<allocator_type, pointer, _Args...>(),
             ^
/usr/include/c++/v1/vector:781:25: note: in instantiation of function template specialization
      'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int,
      std::__1::default_delete<int> > &>' requested here
        __alloc_traits::construct(__a, _STD::__to_raw_pointer(this->__end_), *__first);
                        ^
/usr/include/c++/v1/vector:924:9: note: in instantiation of function template specialization
      'std::__1::vector<std::__1::unique_ptr<int, std::__1::default_delete<int> >,
      std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::__construct_at_end<std::__1::unique_ptr<int, std::__1::default_delete<int> > *>' requested here
        __construct_at_end(__x.__begin_, __x.__end_);
        ^
dummy.cpp:7:37: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<int,
      std::__1::default_delete<int> >, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::vector' requested here
        std::vector<unique_ptr<int>> bar = foo;
                                           ^
/usr/include/c++/v1/memory:1997:5: note: declared private here
    unique_ptr(const unique_ptr&);
    ^
1 error generated.
 

C'est toujours long et moche, mais à mon avis, beaucoup plus clair quant à ce que / où est le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X