2010-08-27 3 views
5

MSVC 10 und MSVC 9 erzeugen beide eine Level 4-Warnmeldung beim Kompilieren meines Ausnahmeframeworks, obwohl das Verhalten des Programms scheint richtig zu sein. Das Ausnahme-Framework ist ziemlich groß, aber ich habe es geschafft, es auf seine Essenz herunterzukochen. Dies ist ein komplettes Programm, das Sie & Lauf in VS10 kompilierenwarning C4673: werfend 'ex :: traced_error <EX>' die folgenden Typen werden in der Catch-Site nicht berücksichtigt

#include <cstdlib> 
#include <stdexcept> 
#include <string> 
#include <iostream> 
#include <sstream> 
using namespace std; 

    namespace ex 
    { 
     class generic_error : virtual public std::exception 
     { 
     public: 
      generic_error(int thread_id) : thread_id_(thread_id) {} 
      const char* what() const throw() 
      { 
       static std::string msg; 
       stringstream ss; 
       ss << "generic error in thread #" << thread_id_; 
       msg = ss.str(); 
       return msg.c_str(); 
      } 
      int thread_id_; 
     }; 

     template<class EX> 
     class traced_error : virtual public std::exception, virtual public EX 
     { 
     public: 
      traced_error(int line, const EX& ex): EX(ex), line_(line) { } 
      const char* what() const throw() 
      { 
       static std::string msg; 
       stringstream ss; 
       ss << "traced error on line " << line_ << " : '" << EX::what() << "'"; 
       msg = ss.str(); 
       return msg.c_str(); 
      } 
      int line_; 
     }; 

     template<class EX> traced_error<EX> make_traced_error(int line, const EX& ex) 
     { 
      return traced_error<EX>(line, ex); 
     } 
} 

    int main() 
    { 
     try 
     { 
      throw ex::make_traced_error(__LINE__, ex::generic_error(234)); 
     } 
     catch(const ex::generic_error& gex) 
     { 
      cout << "gex = " << gex.what(); 
      return 2; 
     } 
     catch(const exception& ex) 
     { 
      cout << ex.what(); 
      return 1; 
     } 
    } 

Wenn die Zeile Kompilieren throw ex::make_traced_error(__LINE__, ex::generic_error(234)); der Compiler gibt:

1>hacks_vs10.cpp(51): warning C4673: throwing 'ex::traced_error<EX>' the following types will not be considered at the catch site 
1>   with 
1>   [ 
1>    EX=ex::generic_error 
1>   ] 

Eines der Ziele dieser Ausnahme-Bibliothek ist Quelldatei Informationen anhängen jede geworfene Ausnahme. Ich verwende ein Makro, das throw ex::make_traced_error(__FILE_, __LINE__, ex); auswertet, aber das war nicht erforderlich, um die Compilerwarnung zu replizieren.

make_traced_error instanziiert eine Vorlagenausnahmeklasse, deren Vorlagenparameter die Ausnahme ist, die ausgelöst wird, in diesem Fall generic_error. Offensichtlich, wenn ich einfach eine einfache generic_error werfe den Compiler ist glücklich, aber das ist nicht das, was ich tun möchte.

Was ist die Ursache und Wirkung dieser Warnung? Ist der Compiler falsch oder mein Code? Ich sollte hier ein paar Dinge notieren.

Erstens, wenn ich diesen Code ausführen, tut es, was ich erwarte es zu tun. Der generic_error catch-Block wird aufgerufen, anstelle der allgemeinen exception Block, und die Ausgabe des Programms ist:

gex = verfolgt Fehler in Zeile 51:

Zweitens, wenn ich diesen Code mit dem kompilieren Comeau online compiler es kompiliert ohne Fehler oder Warnung und schlägt mir vor, dass mein Code Standards-compliant und legal C++ ist. Richtige Annahme?

'allgemeine Fehler in thread # 234'

Schließlich habe ich die MS knowledge base article über diese Warnung gesehen. Aber die Erklärung von MS war völlig unbefriedigend (sie erklärte nicht die Ursache der Warnung), und ihre Lösung ist inakzeptabel - sie sagen, dass ich einfach eine direkte generic_error werfen sollte.

+2

Ich würde vermuten, dass dies eine falsche Warnung ist. Beachten Sie, dass "die folgenden Typen" angegeben sind, aber keine Typen aufgeführt sind. –

+0

@ James: Ich glaube, die "folgenden Typen" bezieht sich auf die nächste Zeile, in der es 'generic_error' erwähnt. MS-Compiler-Fehler sind oft multi-line –

+0

Der 'mit [...]' Teil gibt an, dass, wenn es sagt "ex :: traceed_error " in der ersten Zeile des Fehlers, die Vorlage Argumente der instanziierten Vorlage sind was im '...' Teil aufgeführt ist. Wenn Sie 'traced_error' so ändern, dass private Vererbung verwendet wird, erhalten Sie eine weitere Zeile, die' ex :: generic_error' als einen Typ aufführt, der bei einer Auffangstelle nicht berücksichtigt wird. –

Antwort

6

Das Problem betrifft indirekt die mehrfache virtuelle Vererbung von std::exception. Der Compiler wird deswegen verwirrt, vergisst aber, Ihnen zu sagen, warum. : -/

James McNellis ist richtig: der Compiler verspricht, einen Typ zu erwähnen, aber es tut es nicht. Versuchen Sie, ohne die template:

#include <stdexcept> 

class Base: virtual public std::exception {}; 
class Derv: public Base, virtual public std::exception {}; 

int main() 
{ 
    try { 
    throw Derv(); 
    } catch (const Base &) { 
    return 2; 
    } catch (...) { 
    return 1; 
    } 
} 

Wenn mit Level 4 Warnungen zusammengestellt, das sagt nichts anderes als:

C4673 Warnung: Werfen ‚Derv‘ die folgenden Typen werden nicht an der Fang-Website angesehen werden

Ich sehe den Wert von Warnungen. Aber offensichtlich ist Stufe 4 in diesem Fall fehlerhaft.Da alles wie erwartet funktioniert, können Sie den Compiler einfach stummschalten:

Ich denke, Sie könnten diesen Fall als einen Fehler an Microsoft melden. Der Compiler sollte den Typ und das Problem angeben.

+0

Mein Code kompiliert gut in Comeau und GCC, und von meinem Lesen des Standards ist es richtig. Das Programm verhält sich auch korrekt. Alle Hinweise darauf, dass es sich tatsächlich um einen Compiler-Bug handelt, aber vor allem, dass es seit VC9 zumindest existiert, will ich sicher sein. Außerdem würde ich die Warnung lieber nicht deaktivieren, da dies nicht nur falsch positive, sondern auch echte positive deaktivieren würde. –

+0

@John Dibling: Glauben Sie mir "es ist so lange dort gewesen" bedeutet nicht, dass es kein Fehler ist. Schau dir dieses Juwel an: http://blogs.msdn.com/b/aszego/archive/2010/05/12/override-atlthrow-with-care.aspx es ist seit VC++ 7 da und ist in VC + vorhanden +10 sicher und niemand weiß, wann es behoben wird. – sharptooth

+0

@John: Das Deaktivieren der Warnung sollte keine echten positiven Informationen verbergen, da sie die Warnung vor der eigentlichen Ursache nicht verbergen. In dem in MSDN beschriebenen Fall: 'warning C4670: 'Base': auf diese Basisklasse kann nicht zugegriffen werden. ' –

Verwandte Themen