Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Visual C++ admite transmitir una excepción desde un subproceso a otro.Transportar excepciones permite detectar una excepción en un subproceso y después para que la excepción que se produce en un subproceso diferente.Por ejemplo, puede utilizar esta característica para escribir una aplicación multiproceso donde el subproceso primario controla todas las excepciones producidas por los subprocesos secundarios.Transportar excepciones es útil principalmente a los programadores que crean las bibliotecas de programación o sistemas paralelos.para implementar transportar excepciones, Visual C++ proporciona el tipo de exception_ptr y current_exception, rethrow_exception, y las funciones de copy_exception .
namespace std
{
typedef unspecified exception_ptr;
exception_ptr current_exception();
void rethrow_exception(exception_ptr p);
template<class E>
exception_ptr copy_exception(E e);
}
Parámetros
Parámetro |
Descripción |
|---|---|
unspecified |
una clase interna sin especificar que se utiliza para implementar el tipo de exception_ptr . |
p |
un objeto de exception_ptr que hace referencia una excepción. |
E |
una clase que representa una excepción. |
e |
Una instancia de la clase de E del parámetro. |
Valor devuelto
La función de current_exception devuelve un objeto de exception_ptr que haga referencia a la excepción que está actualmente en curso.Si no hay ninguna excepción en curso, la función devuelve un objeto de exception_ptr que no está asociado a ninguna excepción.
La función de copy_exception devuelve un objeto de exception_ptr que haga referencia a la excepción especificada por el parámetro de e .
Comentarios
Escenario
Imagine que desea crear una aplicación que pueda escalar para controlar una cantidad de trabajo variable.Para lograr este objetivo, diseñe una aplicación multiproceso donde una inicial, subproceso primario crea tantos subprocesos secundarios mientras que necesita para hacer el trabajo.Los subprocesos secundarios ayudan al subproceso primario para administrar recursos, para equilibrar la carga, y para mejorar el rendimiento.Distribuyendo el trabajo, la aplicación multiproceso funciona mejor que una aplicación de un único subproceso.
Sin embargo, si un subproceso secundario produce una excepción, el subproceso primario para controlarlos.Esto es porque desea que la aplicación para controlar las excepciones de una manera coherente, unificada independientemente del número de subprocesos secundarios.
Soluciones
Para controlar el escenario anterior, el estándar de C++ admite transmitir una excepción entre subprocesos.Si un subproceso secundario produce una excepción, esa excepción se convierte en la excepción actual.Por ejemplo análogo al mundo real, la excepción actual se en vuelo.La excepción actual está en vuelo desde el momento en que se produce hasta el controlador de excepciones que las capturas se devuelven.
El subproceso secundario puede detectar la excepción actual en un bloque de catch , y después llama a la función de current_exception para almacenar la excepción en un objeto de exception_ptr .El objeto de exception_ptr debe estar disponible al subproceso secundario y el subproceso primario.Por ejemplo, el objeto de exception_ptr puede ser una variable global cuyo acceso se controla mediante una exclusión mutua.El transporte del término que una excepción significa que una excepción en un subproceso se puede convertir en un formulario que se puede navegar a otro subproceso.
A continuación, el subproceso principal llama a la función de rethrow_exception , que extrae y inicia la excepción de objeto de exception_ptr .Cuando se produce una excepción, se convierte en la excepción actual en el subproceso primario.Es decir, la excepción se que procede del subproceso primario.
Finalmente, el subproceso primario puede detectar la excepción actual en un bloque y después un proceso de catch él o lanzarla un controlador de excepciones de nivel superior.O, el subproceso primario puede omitir la excepción y permitir que el proceso finalice.
La mayoría de las aplicaciones no tienen que transportar excepciones entre subprocesos.Sin embargo, esta característica es útil en un sistema de cálculo paralelo porque el sistema puede dividir el trabajo entre los subprocesos, los procesadores, o núcleos secundarios.En un entorno informático paralelo, un subproceso único, dedicado pueden controlar todas las excepciones de los subprocesos secundarios y puede mostrar un modelo coherente de control de excepciones a cualquier aplicación.
Para obtener más información sobre la propuesta de comité de normas de C++, busque internet para el número de documento N2179, denominado “compatibilidad con lenguajes para transportar Excepciones entre subprocesos”.
Control de excepciones Modelos y opciones del compilador
El modelo de control de excepciones de aplicación determina si puede detectar y transmitir una excepción.Visual C++ admite tres modelos que pueden controlar excepciones de C++, las excepciones (SEH) de control estructurado de excepciones, y las excepciones (CLR) de Common Language Runtime.Utilice las opciones del compilador de /EH y de /clr de especificar el modelo de control de excepciones en la aplicación.
Sólo la combinación siguiente de opciones del compilador e instrucciones de programación puede llevar una excepción.Otras combinaciones no pueden detectar excepciones, ni pueden detectar pero no puede transportar excepciones.
La opción del compilador /EHa y la instrucción de catchpueden transportar excepciones de SEH y C++.
/EHa, /EHs, y las opciones del compilador de /EHsc y la instrucción de catchpueden transmitir las excepciones de C++.
La opción del compilador /CLR o de /CLR:pure y la instrucción de catchpueden transmitir las excepciones de C++.Las opciones del compilador de /CLR implican la especificación de la opción de /EHa .Observe que el compilador no admite transportar excepciones administradas.Esto es debido a que las excepciones administradas, que son derivadas de la clase de System.Exception , ya sean objetos que puede moverse entre subprocesos utilizando las funciones en tiempo de ejecución común de languange.
Nota sobre la seguridadSe recomienda que especifique la opción del compilador /EHsc y cogemos sólo las excepciones de C++.Se expone a una amenaza de seguridad si se usa la opción del compilador /EHa o de /CLR y una instrucción de catch con una declaración de excepción de puntos suspensivos (catch(...)).Piensa probablemente utilizar la instrucción de catch para capturar algunas excepciones concretas.Sin embargo, la instrucción de catch(...) captura todas las excepciones de C++ y de SEH, incluidas las inesperadas que deben ser irrecuperables.Si se omite o controla mal una excepción inesperada, el código malintencionado puede utilizar esa posibilidad de socavar la seguridad del programa.
Uso
Las secciones siguientes describen cómo transportar excepciones utilizando el tipo de exception_ptr, y current_exception, rethrow_exception, y las funciones de copy_exception .
tipo de exception_ptr
Utilice un objeto de exception_ptr para hacer referencia a la excepción actual o una instancia de una excepción definida por el usuario.En la implementación de Microsoft, una excepción se representa mediante una estructura de EXCEPTION_RECORD .Cada objeto de exception_ptr incluye un campo de referencia de excepción que apunta a una copia de la estructura de EXCEPTION_RECORD que representa la excepción.
Cuando se declara una variable de exception_ptr , la variable no está asociado a ninguna excepción.Es decir, el campo de referencia de excepciones es NULL.Este tipo de objeto de exception_ptr se denomina exception_ptr null.
utilice la función de current_exception o de copy_exception para asignar una excepción a un objeto de exception_ptr .Al asignar una excepción a una variable de exception_ptr , los puntos del campo de referencia de la excepción de la variable a una copia de la excepción.Si hay memoria suficiente para copiar la excepción, los puntos del campo de referencia de la excepción a una copia de una excepción de std:: bad_alloc .Si la función de current_exception o de copy_exception no puede copiar la excepción por cualquier otro motivo, la función la función de terminate (CRT) salir del proceso actual.
A pesar de su nombre, un objeto no es en sí mismo de exception_ptr puntero.No obedece la semántica de puntero y no puede utilizarse con operadores de acceso (->) o de direccionamiento indirecto del miembro de puntero (*).El objeto de exception_ptr no tiene ningún miembro de datos público o las funciones miembro.
comparaciones:
Puede usar los operadores de igual (==) y de no-igual (!=) para comparar dos objetos de exception_ptr .Los operadores no compara el valor binario (configuración de bits) de las estructuras de EXCEPTION_RECORD que representan las excepciones.En su lugar, los operadores comparan las indicaciones del campo de referencia de la excepción de los objetos de exception_ptr .Por consiguiente, exception_ptr NULL y el valor NULL se consideran iguales.
función de current_exception
Llame a la función de current_exception en un bloque de catch .Si una excepción está en vuelo y el bloque de catch puede detectar la excepción, la función de current_exception devuelve un objeto de exception_ptr que haga referencia a la excepción.Si no, la función devuelve un objeto null de exception_ptr .
Detalles:
La función de current_exception captura la excepción independientemente de está en vuelo si la instrucción de catch especifica una instrucción de declaración de excepción .
El destructor para la excepción actual se llama al final de catch bloquea si no lo hace a producir una excepción.Sin embargo, incluso si se llama a la función decurrent_exception en un destructor, la función dedevuelve un objeto de exception_ptr que haga referencia a la excepción actual.
Las llamadas sucesivas a la función de current_exception devuelven objetos de exception_ptr que hacen referencia a distintas copias de la excepción actual.Por tanto, los objetos se comparan como elementos iguales porque se refieren a distintas copias, aunque las copias tienen el mismo valor binario.
ELLA excepciones:
Si utiliza la opción del compilador de /EHa , puede detectar una excepción de SEH en bloque de C++. catch .La función de current_exception devuelve un objeto de exception_ptr que haga referencia a la excepción de SEH.Y la función de rethrow_exception produce una excepción de SEH si se llama al objeto transportadode exception_ptr como argumento.
La función de current_exception devuelve exception_ptr null si se llama a un controlador de terminación de SEH __finally , un controlador de excepciones de __except , o la expresión de filtro de __except .
Una excepción obtener no admite las excepciones anidadas.Una excepción anidada se produce si se inicia otra excepción mientras se manejando una excepción.Si se detecta una excepción anidada, los puntos del miembro de datos de EXCEPTION_RECORD.ExceptionRecord en una cadena de estructuras de EXCEPTION_RECORD que describen las excepciones asociado.La función de current_exception no admite las excepciones anidadas porque devuelve un objeto de exception_ptr cuyo miembro de datos de ExceptionRecord se pone a cero out.
Si se detecta una excepción de SEH, debe administrar la memoria a la que hace referencia el puntero en la matriz de los EXCEPTION_RECORD.ExceptionInformation .Debe garantizar que la memoria es válida durante la duración del objeto correspondiente de exception_ptr , y que la memoria se liberará cuando se elimina el objeto de exception_ptr .
Puede utilizar funciones estructuradas (SE) de traductor de excepción junto con la característica de las excepciones de transporte.Si una excepción de SEH se convierte a la excepción de C++., la función de current_exception devuelve exception_ptr que hace referencia a la excepción traducida en lugar de la excepción original SEH.La función de rethrow_exception produce posteriormente la excepción traducida, no la excepción original.Para obtener más información sobre las funciones del traductor de SE, vea _set_se_translator.
función de rethrow_exception
Después de que se almacene una excepción detectada en un objeto de exception_ptr , el subproceso primario puede procesar el objeto.En el subproceso primario, llame a la función de rethrow_exception junto con el objeto de exception_ptr como argumento.La función de rethrow_exception extrae la excepción de objeto de exception_ptr y inicia la excepción en el contexto del subproceso primario.Si el parámetro de p de la función de rethrow_exception es exception_ptrnull, la función produce std:: bad_exception.
La excepción extraída es ahora la excepción actual en el subproceso primario, y puede controlarlo como haría con cualquier otra excepción.Si se detecta la excepción, puede controlarla inmediatamente o utilizar una instrucción de throw enviada a un controlador de excepciones de nivel superior.Si no, no haga nada y permiten que el controlador de excepciones predeterminado del sistema para terminar el proceso.
función de copy_exception
La función de copy_exception toma una instancia de una clase como argumento y devuelve exception_ptr que haga referencia a la instancia.Generalmente, se especifica un objeto de clase de excepción como argumento a la función de copy_exception , aunque cualquier objeto de la clase puede ser el argumento.
Llamar a la función de copy_exception equivale a producir la excepción de C++., a detectarla en un bloque de catch , y llamando a la función de current_exception para devolver un objeto de exception_ptr que haga referencia a la excepción.La implementación de Microsoft de la función de copy_exception es más eficaz que realmente y después detectando una excepción.
Una aplicación no exige la función de copy_exception , y desalentamos su uso.
Ejemplo
El ejemplo siguiente ofrece una excepción de C++ estándar y una excepción personalizada de C++ a partir de un subproceso a otro.
// transport_exception.cpp
// compile with: /EHsc /MD
#include <windows.h>
#include <stdio.h>
#include <exception>
#include <stdexcept>
using namespace std;
// Define thread-specific information.
#define THREADCOUNT 2
exception_ptr aException[THREADCOUNT];
int aArg[THREADCOUNT];
DWORD WINAPI ThrowExceptions( LPVOID );
// Specify a user-defined, custom exception.
// As a best practice, derive your exception
// directly or indirectly from std::exception.
class myException : public std::exception {
};
int main()
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
// Create secondary threads.
for( int i=0; i < THREADCOUNT; i++ )
{
aArg[i] = i;
aThread[i] = CreateThread(
NULL, // Default security attributes.
0, // Default stack size.
(LPTHREAD_START_ROUTINE) ThrowExceptions,
(LPVOID) &aArg[i], // Thread function argument.
0, // Default creation flags.
&ThreadID); // Receives thread identifier.
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return -1;
}
}
// Wait for all threads to terminate.
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread handles.
for( int i=0; i < THREADCOUNT; i++ ) {
CloseHandle(aThread[i]);
}
// Rethrow and catch the transported exceptions.
for ( int i = 0; i < THREADCOUNT; i++ ) {
try {
if (aException[i] == NULL) {
printf("exception_ptr %d: No exception was transported.\n", i);
}
else {
rethrow_exception( aException[i] );
}
}
catch( const invalid_argument & ) {
printf("exception_ptr %d: Caught an invalid_argument exception.\n", i);
}
catch( const myException & ) {
printf("exception_ptr %d: Caught a myException exception.\n", i);
}
}
}
// Each thread throws an exception depending on its thread
// function argument, and then ends.
DWORD WINAPI ThrowExceptions( LPVOID lpParam )
{
int x = *((int*)lpParam);
if (x == 0) {
try {
// Standard C++ exception.
// This example explicitly throws invalid_argument exception.
// In practice, your application performs an operation that
// implicitly throws an exception.
throw invalid_argument("A C++ exception.");
}
catch ( const invalid_argument & ) {
aException[x] = current_exception();
}
}
else {
// User-defined exception.
aException[x] = copy_exception( myException() );
}
return TRUE;
}
Requisitos
encabezado: <excepción>
Vea también
Referencia
Control de excepciones en Visual C++
Estructura EXCEPTION_RECORD
Sintaxis de controlador