Eccezioni (C++/CX)
La gestione degli errori in C++/CX si basa sulle eccezioni. Al livello più fondamentale, i componenti Windows Runtime segnalano errori come valori HRESULT. In C++/CX questi valori vengono convertiti in eccezioni fortemente tipite che contengono un valore HRESULT e una descrizione stringa a cui è possibile accedere a livello di codice. Le eccezioni vengono implementate come oggetto ref class
che deriva da Platform::Exception
. Lo spazio dei nomi Platform
definisce le classi distinte di eccezioni per i valori HRESULT più comuni; tutti gli altri valori sono segnalati tramite la classe Platform::COMException
. Tutte le classi di eccezioni presentano un campo Exception::HResult che puoi utilizzare per recuperare il valore HRESULT originale. È anche possibile esaminare le informazioni sullo stack di chiamate per il codice utente nel debugger che consente di individuare l'origine originale dell'eccezione, anche se ha avuto origine nel codice scritto in un linguaggio diverso da C++.
Eccezioni
Nel programma C++ puoi generare e intercettare un'eccezione proveniente da un'operazione di Windows Runtime, un'eccezione derivata da std::exception
o da un tipo definito dall'utente. È necessario generare un'eccezione di Windows Runtime solo quando supera il limite dell'interfaccia binaria dell'applicazione ( ABI), ad esempio quando il codice che intercetta l'eccezione viene scritto in JavaScript. Quando un'eccezione C++ non Windows Runtime raggiunge il limite ABI, l'eccezione viene convertita in un'eccezione Platform::FailureException
, che rappresenta un E_FAIL HRESULT. Per ulteriori informazioni su ABI, vedi Creating Windows Runtime Components in C++.
Puoi dichiarare un oggetto Platform::Exception usando uno dei due costruttori che accettano un parametro HRESULT o un parametro HRESULT e un parametro Platform::String^ che possono essere passati attraverso l'ABI a qualsiasi app di Windows Runtime che la gestisce. In alternativa, puoi dichiarare un'eccezione usando uno di due overload del metodo Exception::CreateException che accettano un parametro HRESULT o un parametro HRESULT e un parametro Platform::String^
.
Eccezioni standard
C++/CX supporta un set di eccezioni standard che rappresentano errori HRESULT tipici. Ogni eccezione standard deriva da Platform::COMException, che a sua volta deriva da Platform::Exception
. Quando generi un'eccezione che supera il limite dell'ABI, l'eccezione deve essere di tipo standard.
Non puoi derivare un tipo di eccezione personale da Platform::Exception
. Per generare un'eccezione personalizzata, utilizza un valore HRESULT definito dall'utente per creare un oggetto COMException
.
Nella tabella seguente sono elencate le eccezioni standard.
Nome | HRESULT sottostante | Descrizione |
---|---|---|
COMException | HRESULT definito dall'utente | Generata quando viene restituito un HRESULT non riconosciuto da una chiamata a un metodo COM. |
AccessDeniedException | E_ACCESSDENIED | Generata quando viene negato l'accesso a una risorsa o a una funzionalità. |
ChangedStateException | E_CHANGED_STATE | Generata quando i metodi di un iteratore di raccolta o di una visualizzazione di raccolta vengono chiamati dopo che la raccolta padre è stata modificata, invalidando così i risultati del metodo. |
ClassNotRegisteredException | REGDB_E_CLASSNOTREG | Generata quando una classe COM non è stata registrata. |
DisconnectedException | RPC_E_DISCONNECTED | Generata quando un oggetto viene disconnesso dai relativi client. |
FailureException | E_FAIL | Generata quando un'operazione non viene completata correttamente. |
InvalidArgumentException | E_INVALIDARG | Generata quando uno degli argomenti forniti a un metodo non è valido. |
InvalidCastException | E_NOINTERFACE | Generata quando non è possibile eseguire il cast di un tipo a un altro tipo. |
NotImplementedException | E_NOTIMPL | Generata se un metodo di interfaccia non è stato implementato in una classe. |
NullReferenceException | E_POINTER | Generata quando viene effettuato un tentativo di dereferenziare un riferimento di oggetto null. |
ObjectDisposedException | RO_E_CLOSED | Generata quando viene eseguita un'operazione su un oggetto eliminato. |
OperationCanceledException | E_ABORT | Generata quando un'operazione viene interrotta. |
OutOfBoundsException | E_BOUNDS | Generata quando un'operazione tenta di accedere a dati memorizzati al di fuori dell'intervallo valido. |
OutOfMemoryException | E_OUTOFMEMORY | Generata quando la memoria disponibile non è sufficiente per completare l'operazione. |
WrongThreadException | RPC_E_WRONG_THREAD | Generata quando un thread esegue una chiamata tramite un puntatore a interfaccia che è per un oggetto proxy che non appartiene all'apartment del thread. |
Proprietà Message e HResult
Tutte le eccezioni presentano una proprietà HResult e una proprietà Message . La proprietà Exception::HResult ottiene il valore HRESULT numerico sottostante dell'eccezione. La proprietà Exception::Message ottiene la stringa fornita dal sistema che descrive l'eccezione. In Windows 8 il messaggio è disponibile solo nel debugger ed è di sola lettura. Ciò significa che non puoi modificarlo quando generi di nuovo l'eccezione. In Windows 8.1 puoi accedere alla stringa di messaggio a livello di codice e fornire un nuovo messaggio se generi di nuovo l'eccezione. Migliori informazioni sullo stack di chiamate sono inoltre disponibili nel debugger, inclusi gli stack di chiamate per le chiamate asincrone.
Esempi
Questo esempio illustra come generare un'eccezione di Windows Runtime per le operazioni sincrone:
String^ Class1::MyMethod(String^ argument)
{
if (argument->Length() == 0)
{
auto e = ref new Exception(-1, "I'm Zork bringing you this message from across the ABI.");
//throw ref new InvalidArgumentException();
throw e;
}
return MyMethodInternal(argument);
}
Nell'esempio riportato di seguito viene illustrato come intercettare l'eccezione.
void Class2::ProcessString(String^ input)
{
String^ result = nullptr;
auto obj = ref new Class1();
try
{
result = obj->MyMethod(input);
}
catch (/*InvalidArgument*/Exception^ e)
{
// Handle the exception in a way that's appropriate
// for your particular scenario. Assume
// here that this string enables graceful
// recover-and-continue. Why not?
result = ref new String(L"forty two");
// You can use Exception data for logging purposes.
Windows::Globalization::Calendar calendar;
LogMyErrors(calendar.GetDateTime(), e->HResult, e->Message);
}
// Execution continues here in both cases.
//#include <string>
std::wstring ws(result->Data());
//...
}
Per intercettare le eccezioni generate durante un'operazione asincrona, usare la classe task e aggiungere una continuazione di gestione degli errori. La continuazione di gestione degli errori effettua il marshalling delle eccezioni generate in altri thread nel thread chiamante affinché tu possa gestire tutte le potenziali eccezioni da un unico punto nel codice. Per altre informazioni, vedere Programmazione asincrona in C++.
Evento UnhandledErrorDetected
In Windows 8.1 puoi sottoscrivere l'evento statico Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , che fornisce l'accesso a errori non gestiti che stanno per arrestare il processo. Indipendentemente dall'origine, l'errore raggiunge il gestore come oggetto Windows::ApplicationModel::Core::UnhandledError passato con gli argomenti dell'evento. Quando chiami Propagate
sull'oggetto, crea e genera un'eccezione Platform::*Exception
del tipo corrispondente al codice di errore. Nei blocchi catch puoi salvare lo stato utente, se necessario, quindi consentire il termine del processo chiamando throw
oppure ripristinare uno stato noto del programma. 'esempio seguente mostra il modello di base:
In app.xaml.h:
void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);
In app.xaml.cpp:
// Subscribe to the event, for example in the app class constructor:
Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected += ref new EventHandler<UnhandledErrorDetectedEventArgs^>(this, &App::OnUnhandledException);
// Event handler implementation:
void App::OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e)
{
auto err = e->UnhandledError;
if (!err->Handled) //Propagate has not been called on it yet.
{
try
{
err->Propagate();
}
// Catch any specific exception types if you know how to handle them
catch (AccessDeniedException^ ex)
{
// TODO: Log error and either take action to recover
// or else re-throw exception to continue fail-fast
}
}
Osservazioni:
C++/CX non usa la finally
clausola .
Vedi anche
Riferimenti al linguaggio C++/CX
Riferimenti a spazi dei nomi