2017-12-06 47 views
1

Dies ist how to throw gewöhnliche Win32 Fehler korrekt, automatisch die Fehlerbeschreibung abrufen, und es funktioniert wunderbar gut:Wie man eine std :: system_error Ausnahme von einem FAILED (HRESULT) wirft?

if (!SomeWinFunc()) { 
    throw std::system_error(GetLastError(), 
    std::system_category(), 
    "SomeWinFunc crashed badly"); 
} 

aber ich bin unsicher, wie sie mit COM-Fehler zu behandeln, die idiomatically wie folgt geprüft werden:

HRESULT hr = comObj->SomeFunc(); 
if (FAILED(hr)) { 
    throw std::system_error(hr, // <-- is it correct here? 
    std::system_category(), 
    "SomeFunc crashed right now"); 
} 

ist es richtig, ein HRESULT zu system_error passieren, oder es gibt einen anderen Weg, um Ausnahmen von einer COM-Funktion zu werfen?

+0

Haben Sie damit irgendwas erreicht? –

+0

@MichaelGunter, ich habe immer noch keine 100% korrekte Lösung implementiert (möglicherweise beginnend mit Ihrem Code), aber da meine Bedürfnisse einfach mit System-COM-Objekten zu tun haben, funktioniert der Ansatz, den ich in der Frage geschrieben habe, mehrere Tests. Ich plane, tiefer zu gehen, sobald ich Zeit finde. – Rodrigo

Antwort

3

Normalerweise handle ich dies mit dem Microsoft-Standard _com_error Ausnahmetyp, die leicht von einem der folgenden ausgelöst werden kann.

_com_util::CheckError(hr); // throws when FAILED(hr) 
_com_issue_error(hr); // throws always 

Ein Win32-Fehler kann zu einem HRESULT wie so umgewandelt werden:

hr = HRESULT_FROM_WIN32(GetLastError()); 

Dies bedeutet jedoch, dass Sie mit einem neuen Ausnahmetyp zu tun haben, was problematisch sein kann. Um dies auf die reine STL-Weise zu tun, denke ich, dass Sie eine neue error_category ableiten und diese anstelle von verwenden müssen. Ich würde die <system_error> Kopfzeile betrachten und die Implementierung von kopieren und bei Bedarf für HRESULT s aktualisieren.

Idealerweise würden die verschiedenen facility codes im HRESULT durch verschiedene error_category Implementierungen bedient werden - dies würde sehr effektiv die Ausnahme und ihre Quelle kommunizieren. Aber das ist knifflig, und Sie können wahrscheinlich mit einer einzigen com_category, die HRESULT s generisch behandelt.

+0

Es ist wichtig zu beachten, dass Sie ** ein HRESULT nicht übergeben müssen, wenn Sie die "std :: system_category" als Kontext verwenden. Diese Kategorie ist für die Verwendung mit Fehlercodes vorgesehen, die von "GetLastError" zurückgegeben werden. Wenn Sie beispielsweise den COM-Erfolgscode 'S_FALSE' übergeben, wird dies als' ERROR_INVALID_FUNCTION' interpretiert. Informationen zur Implementierung Ihrer benutzerdefinierten 'error_category' finden Sie unter [Systemfehlerunterstützung in C++ 0x - Teil 4] (http://blog.think-async.com/2010/04/system-error-support- in-c0x-part-4.html). – IInspectable

+1

@Intspectable 'S_FALSE' ist kein gutes Beispiel, weil es kein Fehlercode ist. Also gibt es keinen Grund, es zu werfen. Die * error * -Werte, die ein 'HRESULT' darstellen kann, überschneiden sich nicht mit den Fehlercodes, die von' GetLastError' zurückgegeben werden, da 'HRESULT'-Fehler immer negativ sind. Daher ist meiner Meinung nach eine spezielle Kategorie für "HRESULT" nicht erforderlich, da nur Werte geworfen werden, für die "FAILED (hr) == true". – zett42

+0

@ zett42: Das hängt von Ihrer Code Logik ab. Ein erfolgreicher COM-Aufruf kann eine Bedingung liefern, von der Sie nicht wiederherstellen können und die Sie werfen müssen. Selbst wenn dies nicht der Fall wäre, benötigen Sie immer noch eine benutzerdefinierte Fehlerkategorie, um Fehlermeldungen zu erzeugen. Während "FormatMessage" mit systemdefinierten 'HRESULT'-Werten verwendet werden kann, sehen die Dinge anders aus, wenn Sie mit benutzerdefinierten Codes arbeiten. Sie benötigen zusätzliche Informationen, um diese in Fehlermeldungen umzuwandeln, nämlich das Modul-Handle. Dies muss in der Kategorie codiert werden, da neben dem Fehlercode keine zusätzlichen Informationen übergeben werden können. – IInspectable

Verwandte Themen