2009-02-05 9 views
10

Tengo una aplicación Linux C++ y me gustaría probar la validez de un puntero a un objeto antes de desreferenciarlo. Sin embargo, try/catch no funciona para esto en Linux debido a la falla de segmentación. ¿Cómo puede hacerse esto?Intente/Capture un error de segmentación en Linux

Respuesta

8

Si tiene un escenario donde muchos punteros en su aplicación hacen referencia a los mismos objetos de vida útil limitada, una solución popular es usar boost smart pointers. Editar: en C++ 11, ambos de estos tipos están disponibles en la biblioteca estándar

Usted desea utilizar shared_ptr de puntero (s) que son responsables de la vida de su objeto y weak_ptr para los otros punteros , que puede convertirse en inválido. Verá que weak_ptr tiene la verificación de validez que está solicitando.

+0

No he usado shared_prt, pero por lo que tengo entendido, es un puntero que controla el tiempo de vida del objeto. Tengo una situación opuesta. Tengo un objeto que puede eliminarse al recibir un mensaje. Necesito que aquellos que lo señalan tengan una manera de saber que poseen s puntero no válido – jackhab

+1

Ese es exactamente el tipo de caso para el que está hecho weak_ptr. El weak_ptr dejará que el objeto muera e informará la invalidez si luego intenta acceder al objeto a través del weak_ptr. ¡Una solución mucho mejor que atrapar SIGSEGV! – timday

+0

Eso es lo que pensé que era tu situación. El mensaje "eliminarme" debería restablecer el shared_ptr único. Después de eso, todos los weak_ptr's hechos de ese shared_ptr sabrán que son inválidos. Echa un vistazo al enlace weak_ptr para ver ejemplos. –

4

Inicialice su puntero a NULL. Si después de algún procesamiento sigue siendo NULL, no es válido; de lo contrario, es válido.

+0

Si elimino un objeto que es el puntero no es NULO, pero apunta a la memoria no válida. ¿Cómo puedo validar ese puntero? – jackhab

+1

¿Por qué diablos querrías? Lo borraste Si está utilizando punteros en cualquier lugar y no está seguro de si están eliminados o no, está haciendo algo MUY incorrecto. – Bombe

+0

Yo en segundo lugar. Los punteros inválidos son punteros no válidos. Luego, ya no se puede acceder a la variable de puntero, o la configura en 0. O, como esto es C++, aprenda acerca de RAII. – gimpf

4

Puede habilitar un manejador de señal para SIGSEGV para esta ocasión. Vea la "señal" de la página del manual para más detalles. La otra alternativa es usar referencias que garanticen ser válidas. Depende de tu aplicación, por supuesto.

+0

La página man dice que el estado del proceso no está definido si ignora el SIGSEGV. ¿Puedo reanudar la aplicación C++ después de atrapar SIGSEGV? – jackhab

+0

Buena pregunta, probablemente no de manera segura. Creo que, en general, es mejor usar referencias en lugar de punteros si te preocupa la validez. Como han señalado los otros carteles, puede iniciar sesión donde ocurre el error y corregirlo. –

+0

No se garantiza que las referencias sean válidas. Si la duración del objeto al que se hace referencia finaliza antes de que se utilice la referencia, los resultados tampoco están definidos (en la práctica, son idénticos a un puntero no válido). Las referencias no se pueden inicializar a nulo y no a restablecer. Eso es. – gimpf

8

Un error de segmentación no es una excepción (como la NullPointerException de Java); es una señal enviada desde el SO al proceso. Eche un vistazo a the manpage for sigaction para ver los consejos sobre cómo instalar un controlador para el error de segmentación (SIGSEGV).

1

¿Cómo se prueba la validez del puntero? Comparar con NULL?

Lo mejor que puede hacer es ejecutar su programa bajo Valgrind. Un error puede estar en un lugar bastante diferente.

Actualización: en la plataforma Win32 hay algo así como __try __except que permite detectar algunas excepciones. Hasta donde sé, no hay un equivalente de Linux para esa función de Win32.

+0

En Windows puedes ver una excepción cuando accedes a un puntero para desasignar objetos y puedes manejar la situación. En Linux obtienes SIGSEGV. Mi pregunta es si hay alguna forma de validar un puntero que una vez apuntó a un objeto y por lo tanto no es NULL pero aún invalidado por el operador de eliminación. – jackhab

+0

No soy experto en Win32 pero una vez que utilicé __try __ excepto por tales cosas. –

+0

Esas cosas solo para Windows, exponiendo la "Excepción estructurada" de la plataforma manejo "(SEH) en C++. El equivalente de Linux es señales ... pero creo que la sugerencia de Shmoopty de shared_ptr/weak_ptr está más en la línea correcta. – timday

0

Si adjunta un controlador al SIGSEGV, no hay mucho que pueda hacer además de registrar el hecho de que el error ocurrió y fallar correctamente. Su programa se encuentra en un estado indefinido cuando ocurre esta infracción y, por lo tanto, puede no ser seguro continuar con la operación normal.

Más allá de buscar NULL No creo que haya una manera de comprobar si un puntero es "válido" en el sentido que está describiendo. Durante la operación normal, errores como este no deberían ocurrir, ya que representan un error, por lo que debería querer que su programa falle, aunque con gracia.

0

Los punteros se almacenan en objetos. Se inicializan en el constructor, potencialmente a 0 (NULO). Se eliminan en el destructor, posiblemente en la asignación y rara vez en otras funciones. Cuando se eliminan en miembros que no sean el destructor, se les asigna inmediatamente un nuevo valor o 0.

2

No existe una forma natural y universal con los punteros sin formato de C++. C++ supone que hará un seguimiento de esa información.

En la mayoría de las situaciones, puede manejar esto recordando establecer punteros a NULL cuando no son válidos. Los nuevos punteros que inicialmente no apuntan deben establecerse en NULL y los objetos recién eliminados deben tener sus punteros establecidos en NULL.

Cuestiones relacionadas