MS Code Analyse
-
Kann ich so blöd sein? Wo soll ich denn noexcept hinschreiben?
-
@tormen_bln sagte in MS Code Analyse:
- C26455/C26439 ist keine harte Regel, sondern bloss was MS gut & richtig findet. Kann man so sehen, muss man aber nicht. Das "may not" im Text der Warning ist also übertrieben, die korrekte Formulierung wäre eher "should not".
- C26455/C26439 wird u.A. bei Default-Konstruktoren erzeugt wenn diese nicht
noexcept
markiert sind. - Die Frage wo du - im Zusammenhang mit C26455/C26439 in Zeile 11 - in deinem Code noch
noexcept
hinschreiben sollte kann man mit "nirgends" beantworten. Denn: DerWinAPI
Default-Konstruktor kann Exceptions werfen, da er einen std::string mit nicht-leerem Inhalt initialisieren muss. Was nichtnoexcept
geht.
Wenn du die Warning vermeiden willst bleiben dir folgende Möglichkeiten:
a) Entferne den
WinAPI
Default-Konstruktor. D.h. er muss nen Parameter bekommen der keinen Default-Wert hat. Der naheliegende Kandidat wäre der "last error" Wert. Den Aufruf vonGetLastError
imWinAPI
Konstruktor halte ich sowieso für schlechten Stil. Grund: wenn manGetLastError
nicht direkt sofort nach dem fehlgeschlagenen Aufruf macht, kann man kaum sicherstellen dass dazwischen nicht ein weiterer WinAPI Aufruf gemacht wurde, der evtl. den "last error" Wert ändert. D.h. man kann kaum sicher stellen dass man den richtigen Fehlercode bekommt. Den User zu zwingenGetLastError
selbst aufzurufen könnte man also sogar als Verbesserung ansehen (ich sehe das so).
Wenn du unbedingt einen Convenience-Helper möchtest derGetLastError
aufruft und dir ein damit initialisiertesWinAPI
Exception Objekt gibt kannst du das ja leicht machen, z.B. indem duWinAPI
eine statische FunktionfromLastError
gibst die einWinAPI
Objekt zurückgibt und ca. so aussehen könnte:class WinAPI ... { // ... static WinAPI fromLastError() { auto const errorCode = ::GetLastError(); // Das sollte auf jeden Fall die erste Anweisung in dieser // Funktion bleiben, sonst besteht wieder die Gefahr dass du den falschen Wert bekommst return WinAPI{ errorCode }; } // ... };
b) Ändere deine Exception-Klasse so, dass die Fehlermeldung erst zusammengebaut wird wenn
getMessage
bzw.getDetailedDescription
aufgerufen werden. Dann könntest du statt einenstd::string
zu initialisieren imWinAPI
Default-Konstruktor einfach nur den Fehlercode im Objekt ablegen (wasnoexcept
geht, ist ja bloss einDWORD
), undFormatMessage
erst ingetMessage
bzw.getDetailedDescription
aufrufen.Eine weitere Beobachtung: Exceptions sollten immer noexcept-kopierbar sein. Sonst kann es passieren dass beim Fangen einer Exception wieder eine Exception erzeugt wird, was dann aua ist. Die einfachste Möglichkeit das zu erreichen, ist alles was beim Kopieren Allokationen erfordert (bzw. allgemein alles was beim Kopieren Exceptions werfen kann) in eine kleine Hilfs-
struct
zu packen, und in der Exception-Klasse dann nur einenshared_ptr<HelperStruct const>
zu halten. Dashared_ptr
noexcept
zu kopieren ist löst das das Problem. Bzw. wenn gar nichts gehalten werden muss was beim Kopieren werfen könnte (so wie hier wenn du Variante (b) wählst), gibt es sowieso kein Problem.Noch ein letzter Punkt: sei mit
noexcept
sehr vorsichtig. Wenn du an eine Funktionnoexcept
dranschreibst, dann garantierst du damit dass aus der Funktion keine Exceptions rausfliegen. Anders als beiconst
oder ähnlichen Dingen hilft dir der Compiler allerdings nicht dabei dieses Versprechen zu halten, indem er dir einen Fehler um die Ohren wirft wenn dunoexcept
wo dazuschreibst "wo es nicht hingehört". Statt dessen wird das Programm fehlerfrei übersetzt, und wenn während der Laufzeit dann eine Exception aus einernoexcept
Funktion rausfliegen würde (weil du nicht aufgepasst hast), dann wird an der Stelle statt dessen einfach dein Programm abgebrochen -std::terminate
. Schwupps-weg, einfach so.
Möglicherweise wird dir der Static Analyzer bei solchen Fehlern eine Warnung geben (-> C26447), aber verlassen sollte man sich mMn. nicht unbedingt darauf.ps:
c) Markiere deinen Default-Konstruktor alsnoexcept(false)
. Das sollte den Static Analyzer von Visual Studio wissen lassen dass du dir darüber im Klaren bist dass der Konstruktor nichtnoexcept
ist, und die Warnung sollte nicht mehr kommen. Zumindest steht das so hier https://developercommunity.visualstudio.com/content/problem/236762/c-code-analysis-warning-c26439-this-kind-of-functi.html beschrieben.
-
Dieser Beitrag wurde gelöscht!
-
@hustbaer Vielen, vielen Dank und sorry, dass meine Antwort so spät kommt. Das ist mal eine Aussage, mit der ich etwas anfangen kann. Auch die Tipps zum schlechten Stil, danke nochmals. Ich werde das alles umbauen und bin somit diese Warnungen erstmal los. Gibt ja noch weitere, die bearbeitet werden wollen
Auch Dank an alle anderen, die versucht haben, mir zu helfen.
MfG Torsten