2017-03-23 2 views
1

Der folgende Vergleich nicht für einen Fehler, den gibt "asio.misc" für errorCode.category(). Name() und "Ende der Datei" für errorCode.message()vergleichen boost :: system :: error_category

Wenn es behauptet, in der Kategorie asio.misc zu sein, warum wird dann die if-Bedingung von (errorCode.category() == boost :: asio :: error :: misc_category) zu false ausgewertet?

Googeln (einschließlich Antworten hier) sagt, dass ein boost :: system :: error_code den gleichen Wert in mehr als einer Kategorie haben kann, also nehme ich an, dass, um die richtige Nachricht und Bedeutung zu bekommen, wir Boost vergleichen müssen :: system :: error_category sowie boost :: system :: error_code :: value.

Wie vergleichen wir die Kategorie richtig, wenn dies nicht funktioniert?

-Code in Frage:

//-------------------------------------------------------------------------------------------------- 
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:

Nach https://theboostcpplibraries.com/boost.system und Boost::file_system: Checking error codes

Menschen häufig und fälschlicherweise Code schreiben, nur um den Fehlerwert zu vergleichen und nicht die Kategorie. Der Fehlerwert allein ist nicht eindeutig und kann in mehr als einer Kategorie vorkommen. Benutzer können auch ihre eigenen Fehlercodes und Kategorien erstellen. Daher müssen beide verglichen werden. Dies, so nehme ich an, wirkt sich nicht auf eine große Anzahl von Anwendungen aus, da sie nur ein Feature oder eine Bibliothek verwenden, um ihr Projekt aufzustocken und/oder die Mehrzahl der Fehlercodes auf Windows-Fehlercodes abgebildet sind, die sich am besten bemühen kollidieren.

Ich musste auf einen anderen Computer gehen, um die Boost-Mailing-Liste zu öffnen, da meine Arbeit fast alles blockiert.

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

Nach einem fella da drüben, der Grund ist der Vergleich fehlschlägt, weil die Boost-Bibliothek ist statisch gelinkt und boost :: system :: error_category :: operator == vergleicht Adressen, so dass der LHS ist die Adresse in einer Bibliothek und die RHS ist die Adresse in einer anderen. Sie werden nicht gleich sein, wenn sie erwartet werden.

Die Verwendung der Adresse für Operator == scheint eine sehr alberne Zug für mich. Ich werde weiterhin auf der Boost-Mailing-Liste darüber reden und hier für andere bearbeiten, wenn neues Wissen entdeckt wird.

Vorerst bin ich dynamisch verknüpfen und verwenden Form

//-------------------------------------------------------------------------------------------------- 
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(); 
} 

jedoch dies nicht funktioniert, wenn ich statisch verknüpfen entweder zu steigern. Wenn jemand noch mehr Vorschläge hat, wie wir boost :: system :: error_code richtig vergleichen und die erwarteten Ergebnisse erhalten, dann lasst uns dem auf den Grund gehen.

+2

Wenn Sie nur die Nachricht möchten, rufen Sie einfach 'errorCode.message()'. Dadurch erhalten Sie die entsprechende Nachricht. Wenn Sie verstehen möchten, um was für einen Fehler es sich handelt, verwenden Sie den 'value()'. Ich sehe nicht, warum der Vergleich fehlschlagen würde, der 'operator ==' ist definiert, um Zeiger zu überprüfen (das Fehlercodesystem verwendet statische Instanzen von Kategorien ..) Vielleicht können Sie die Adresse von 'errorCode.category()' und überprüfen 'boost :: asio :: error :: misc_category' um zu sehen, ob sie tatsächlich gleich sind? – Nim

+0

Ich möchte keine Nachricht eingebaut werden. Ich möchte meine eigene Botschaft produzieren, die mein QA-Team beim Lesen meines Protokolls verstehen wird. Joe Bob Tester wird nicht wissen, was "Ende der Datei" bedeutet. –

+0

debugMsg = "Fehlerkategorie: asio.misc. Fehlermeldung: Dateiende." & (errorCode.category()) = 0x016e3768. & (boost :: asio :: error :: misc_category) = & 0x536c1250 –

Antwort

1

Der C++ 11-Standard besagt, dass jede Fehlerkategorie-Instanz eine global eindeutige Adresse haben muss und Vergleiche der Gleichheit diese Adresse zum Vergleich verwenden sollen. Leider ist dies in tragbarem Code nicht zuverlässig, nur die Dinkumware STL implementiert echte Eindeutigkeit der Adresse überall in dem Prozess, und es fügt eine volle Speicherbarriere hinzu, um zu erreichen, d. H. Es ist teuer.

Boost die Qualität der Implementierung ist die gleiche wie libstdC++ oder libC++, Sie können mehrere Instanziierungen unter bestimmten Umständen und diese können unterschiedliche Adressen haben.

In meinem eigenen Code, mache ich zuerst den Vergleichsoperator, und wenn das fehlschlägt, gebe ich eine strcmp() der Kategorie name(). Bis heute hat mich das nicht gebissen. Ich persönlich würde diesen Aspekt der Fehlerkategorien zu einem Fehler im Standard, wie angegeben, erzwingt nicht-Header-only Implementierung, wenn Sie wollen, dass es konform ist, und sogar das nicht Abdeckung RTLD_LOCAL, die Sie bedeutet müssen auf freigegebenen Speicher oder einige Hack zurückgreifen.

+0

Können Sie näher auf die Umstände eingehen und/oder haben Sie diesbezüglich Ressourcen (ich bin neugierig)? – Darklighter

+2

Folgen Sie dem Diskussionsfaden unter http://lists.boost.org/boost-users/2017/03/87303.php –

Verwandte Themen