2017-03-23 1 views
1

La comparaison suivante échoue pour une erreur qui génère "asio.misc" pour errorCode.category() nom.() Et "la fin du fichier" pour errorCode.message()Comparer boost :: Système :: error_category

S'il prétend être dans la catégorie asio.misc, alors pourquoi la condition if de (errorCode.category() == boost :: asio :: error :: misc_category) est-elle fausse? Google (y compris les réponses ici) dit qu'un boost :: system :: error_code peut avoir la même valeur dans plus d'une catégorie, donc je suppose que pour obtenir le bon message et la signification, nous devons comparer boost :: system :: error_category ainsi que boost :: system :: error_code :: value.

Comment comparer correctement la catégorie si cela ne fonctionne pas?

code en question:

//-------------------------------------------------------------------------------------------------- 
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode) 
{ 
    std::ostringstream debugMsg; 
    debugMsg << " Error Category: " << errorCode.category().name() << ". " 
      << " Error Message: " << errorCode.message() << ". "; 

    if(errorCode.category() == boost::asio::error::misc_category) 
    { 
     switch (errorCode.value()) 
     { 
     case boost::asio::error::eof: 
      debugMsg << ". Server has disconnected."; 
      break; 
     case boost::asio::error::connection_refused: 
      debugMsg << ". Connection Refused"; 
      break; 
     default: 
      debugMsg << ". Unknown Error."; 
      break; 
     } 
    } 
    else 
    { 
     debugMsg << ". Unknown Error category."; 
    } 

    return debugMsg.str(); 
} 

EDIT:

Selon https://theboostcpplibraries.com/boost.system et Boost::file_system: Checking error codes

Les gens souvent et écrire par erreur le code que l'on compare la valeur d'erreur et non la catégorie. La valeur d'erreur seule n'est pas unique et peut apparaître dans plusieurs catégories. Les utilisateurs sont également libres de créer leurs propres codes d'erreur et catégories. Par conséquent, les deux doivent être comparés. Cela, je suppose, n'affecte pas un grand nombre d'applications, car ils utilisent seulement une fonctionnalité ou une bibliothèque pour booster leur projet de toute façon et/ou la majorité des codes d'erreur sont mappés aux codes d'erreur Windows qui font le meilleur effort pour ne pas entrer en collision.

J'ai dû utiliser un autre ordinateur pour accéder à la liste de diffusion boost, car mon travail bloque presque tout.

http://boost.2283326.n4.nabble.com/Compare-boost-system-error-category-td4692861.html#a4692869

Selon un fella là-bas, la raison pour laquelle la comparaison échoue parce que la bibliothèque boost est lié statiquement et boost :: :: système error_category :: opérateur == compare les adresses, LHS est l'adresse dans un lib et le RHS est l'adresse dans un autre. Ils ne vont pas être égaux quand on s'attend à ce qu'ils le soient. L'utilisation de l'adresse pour l'opérateur == me semble être un mouvement très stupide. Je continuerai à m'en vanter sur la liste de diffusion boost et à éditer ici pour d'autres si de nouvelles connaissances sont découvertes.

Pour l'instant, je suis un lien dynamique et utilise la forme

//-------------------------------------------------------------------------------------------------- 
std::string ClientSocketASIO::ErrorCodeToString(const boost::system::error_code & errorCode) 
{ 
    std::ostringstream debugMsg; 
    debugMsg << " Error Category: " << errorCode.category().name() << ". " 
      << " Error Message: " << errorCode.message() << ". "; 

    // IMPORTANT - These comparisons only work if you dynamically link boost libraries 
    //    Because boost chose to implement boost::system::error_category::operator == by comparing addresses 
    //    The addresses are different in one library and the other when statically linking. 
    // 
    // We use make_error_code macro to make the correct category as well as error code value. 
    // Error code value is not unique and can be duplicated in more than one category. 
    if (errorCode == make_error_code(boost::asio::error::connection_refused)) 
    { 
     debugMsg << ". Connection Refused"; 
    } 
    else if (errorCode == make_error_code(boost::asio::error::eof)) 
    { 
     debugMsg << ". Server has disconnected."; 
    } 
    else 
    { 
     debugMsg << ". boost::system::error_code has not been mapped to a meaningful message."; 
    } 

    return debugMsg.str(); 
} 

, mais cela ne fonctionne pas lorsque je créer un lien statique pour stimuler non plus. Si quelqu'un a plus de suggestions sur la façon dont nous devons comparer proprement boost :: system :: error_code et obtenir les résultats attendus, s'il vous plaît allons au fond de cela.

+2

Si vous voulez juste le message, appelez 'errorCode.message()'. Cela vous donnera le message approprié. Si vous voulez comprendre le type d'erreur, utilisez la valeur '()'. Je ne vois pas pourquoi la comparaison échouerait, l'opérateur == 'est défini pour vérifier les pointeurs (le système de code d'erreur utilise des instances statiques de catégories ..) Peut-être pouvez-vous vérifier l'adresse de' errorCode.category() 'et 'boost :: asio :: error :: misc_category' pour voir si elles sont effectivement les mêmes? – Nim

+0

Je ne veux pas intégré dans le message. Je veux produire mon propre message que mon équipe de QA comprendra en lisant mon journal. Joe Bob tester ne va pas savoir ce que signifie "End of File". –

+0

debugMsg = "Catégorie d'erreur: asio.misc. Message d'erreur: fin du fichier." & (errorCode.category()) = 0x016e3768. & (boost :: asio :: error :: misc_category) = & 0x536c1250 –

Répondre

1

La norme C++ 11 implique que chaque instance de catégorie d'erreur doit avoir une adresse globalement unique et les comparaisons d'égalité doivent utiliser cette adresse pour comparer. Malheureusement, ce n'est pas fiable dans le code portable , seul le STL Dinkumware implémente l'unicité d'adresse vraie n'importe où dans le processus et il ajoute une barrière de mémoire complète pour atteindre que c'est cher.

La qualité d'implémentation de Boost est la même que celle de libstdC++ ou libC++, vous pouvez obtenir plusieurs instanciations dans certaines circonstances et celles peuvent avoir des adresses différentes.

Dans mon propre code, je fais d'abord l'opérateur de comparaison, et si cela échoue, je fais un strcmp() du nom de la catégorie(). À ce jour, cela ne m'a pas mordu. Je considère personnellement cet aspect des catégories d'erreur comme étant un défaut dans la norme, comme spécifié, il force l'implémentation non en-tête uniquement si vous voulez qu'il soit conforme, et même cela ne couvre pas RTLD_LOCAL, ce qui signifie que vous besoin de revenir sur la mémoire partagée ou un hack.

+0

Pouvez-vous élaborer sur les circonstances et/ou avez-vous des ressources à ce sujet (je suis curieux)? – Darklighter

+2

Suivez le fil de discussion à http://lists.boost.org/boost-users/2017/03/87303.php –