C++/WinRT throws winrt:: to represent COM exceptions. The wil framework throws ResultÂException for this purpose. How do they interact, and what diagnostic information do they provide?
C++/WinRT hresult_ uses RoÂOriginateÂError to generate a stowed exception which records, among other things, a stack trace for the current thread. This stack trace is stored as part of the hresult_ in the form of a IRestrictedErrorInfo.
The wil framework by default does not use RoÂOriginateÂError, so there is no captured stack trace. However, it does capture the file name and line number in the FailureÂInfo that is stored in the ResultÂException. The FailureÂInfo also contains information to let you correlate multiple failures and see which ones are manifestations of the same underlying failure.
Here’s a little table of what we have so far:
| Â | C++/WinRT | wil |
|---|---|---|
| Thrown type | hresult_ |
ResultÂException |
| Stack trace in thrown object | Yes | No |
| File/line number in thrown object | No | Yes |
| Recorded in wil error log | No | Yes |
Things get more complicated if you include wil/: This tells wil to call RoÂOriginateÂError before throwing the exception, thereby capturing a stack trace. The stack trace is not explicitly saved in the exception object, however. It is stored in a thread-local object that can be retrieved via GetErrorInfo(), and many parts of the system (including C++/WinRT) understand how to retrieve and preserve this extended information, though determining whether any specific scenario preserves the extended information requires investigation.
So now we have this:
| Â | C++/WinRT | wil |
|---|---|---|
| Thrown type | hresult_ |
ResultÂException |
| Stack trace in thrown object | Yes | No |
| Stack trace in thread data | Yes | Requires result_ |
| File/line number in thrown object | No | Yes |
| Recorded in wil error log | No | Yes |
But wait, we’re not done yet. There’s another header file that affects how wil throws exceptions, and that’s wil/. This header file enables various C++/WinRT+wil interop features, including exception handling. Exceptions propagated by the C++/WinRT library (for example, by check_) are filtered through wil, which logs them through its own error logging channel. However, since the file and line number were generated from the __FILE__ and __LINE__ preprocessor symbols captured by the THROW_ macro, C++/WinRT cannot capture file and line number information about the origination point, so you don’t get line number information in your wil trace log. But you still get a stack trace in the hresult_ object.
Exceptions that are thrown explicitly via throw hresult_error() do not go through wil filtering.
| Â | C++/WinRT | wil | ||
|---|---|---|---|---|
no wil/ |
with wil/ |
 | ||
throw hresult_ |
check_ |
THROW_ |
||
| Thrown type | hresult_ |
hresult_ |
hresult_ |
ResultÂException |
| Stack trace in thrown object | Yes | Yes | Yes | No |
| Stack trace in thread data | Yes | Yes | Yes | Requires result_originate.h |
| File/line number in thrown object | No | No | No | Yes |
| Recorded in wil error log | No | No | Yes | Yes |
But wait, we’re not finished yet. The wil framework alters its behavior if C++/CX is enabled. If so, then it throws a Platform:: instead of a wil::. The Platform:: captures a stack trace but not file/line number information.
| Â | C++/WinRT | wil | |||
|---|---|---|---|---|---|
no wil/ |
with wil/ |
no C++/CX | with C++/CX | ||
throw hresult_ |
check_ |
THROW_ |
THROW_ |
||
| Thrown type | hresult_ |
hresult_ |
hresult_ |
ResultÂException |
Exception^ |
| Stack trace in thrown object | Yes | Yes | Yes | No | Yes |
| Stack trace in thread data | Yes | Yes | Yes | Requires result_ |
Yes |
| File/line number in thrown object | No | No | No | Yes | No |
| Recorded in wil error log | No | No | Yes | Yes | Yes |
0 comments