2011-10-05 24 views
8

Tengo un código donde uso un puntero para acceder a un bloque de datos. En algunos casos excepcionales, algunos miembros del bloque de datos están vacíos y, como resultado, el puntero se queda colgando. De hecho, obtengo el puntero correcto pero el programa falla al intentar hacer algo con el puntero.¿Hay alguna manera de verificar si el puntero está colgando?

El consejo habitual sería evitar este tipo de uso. Pero lamentablemente, el marco que uso requiere que use este tipo de métodos de acceso a datos.

¿Hay alguna forma de que pueda "verificar" si el puntero no es válido antes de realizar cualquier operación con él? Comprobar que el puntero no es igual a NULL no funcionó, obviamente. También probé esto:

try 
{ 
    CString csClassName = typeid(*pMyPointer).name(); // Check error condition 
    // The line below fails due to dangling pointer (data block is not valid). 
    hr = pMyPointer->MyPointerMethod(); 
} 
catch(bad_typeid) 
{ 
    return E_FAIL; 
} 
catch(...) 
{ 
    return E_FAIL; 
} 

¿Es la manera correcta?

Respuesta

5

No hay forma de comprobar si un puntero sin formato es válido o no. Los punteros no válidos no tienen garantía de que fallan cuando accede a ellos. En lugar de utilizar un puntero sin formato, debe usar alguna forma de puntero inteligente.

+0

Mi puntero debe ser estático para la clase ... ¿está bien si utilizo punteros inteligentes? – Nikhil

+0

Eso no es problema en absoluto. Debe tener cuidado con los problemas de seguridad del hilo, pero eso no es diferente para un puntero inteligente frente a un puntero sin formato. –

+2

No creo que importe. Lo único que me molesta es si su marco puede hacer que sus punteros cuelguen sin previo aviso. Mira, tendrás que extraer el puntero sin formato del puntero inteligente y pasarlo a tu marco. Si garantiza que el puntero seguirá siendo válido después de la llamada, o que se le informará en caso de que se vuelva inválido, bien, vaya por ello. – Septagram

7

Creo que está mirando en la dirección incorrecta. Probablemente tengas un error por el cual no estás inicializando correctamente los punteros, eliminando los objetos demasiado pronto e intentando reutilizar el puntero una vez que se ha eliminado o algo por el estilo. Si ese es el caso, debe centrarse en determinar por qué está sucediendo y solucionar el error, en lugar de tratar de encontrar una forma de ocultar el error.

A partir del enfoque que está utilizando con el operador typeid, la respuesta es que no es válido. Para objetos de tipos que no contienen funciones virtuales, el operador typeid se resuelve en tiempo de compilación en función del tipo estático del puntero. Para los objetos que contienen al menos una función virtual, se resuelve en tiempo de ejecución, pero llamar al typeid(p) con un puntero no válido es un comportamiento indefinido, y de la misma manera que parece funcionar, puede bloquearse.

El uso de punteros inteligentes que se ha sugerido, podría depender de lo que realmente hace la biblioteca y de si puede pasar los punteros inteligentes en todo momento o no. En general, es una buena idea utilizar punteros inteligentes para la administración de memoria, y eso a su vez garantizará que los punteros se inicialicen correctamente (corrija si el problema es la inicialización) y porque ya no está delete manualmente, es probable que si el problema es con la eliminación temprana que ya no sucederá. Pero tenga en cuenta que si bien esto podría resolver el problema, todavía creo que debe comprender por qué el puntero no es válido en su aplicación, ya que podría ser un síntoma de un problema mayor.

Ahora, en la pregunta original de cómo comprobar si el puntero está colgando o no, no puede hacerlo en el programa, pero puede ejecutar su programa dentro de los depuradores de memoria (valgrind en linux, Purify o un conjunto de otros en Linux) y la herramienta podrá ayudarlo a determinar si el puntero nunca se inicializó, o si liberó la memoria en el sistema antes del uso incorrecto.

+0

Gracias por su explicación detallada. Puedo entender que debería encontrar una solución en lugar de ocultar el error ... Pero hay una laguna en el marco diseñado que no puedo cambiar en poco tiempo. Así que estaba buscando una solución por un tiempo. .Traté con punteros inteligentes también, pero no funcionó. – Nikhil

1

No necesita punteros inteligentes. Son solo un posible enfoque para lidiar con este problema.

Puede usar referencias recíprocas: Dentro del objeto al que se hace referencia (referenciae), una lista de referencias a aquellos objetos que hacen referencia a ella (referenciadores). Cuando sea el momento de desasignar la referencia, primero ejecute su lista de referenciadores y establezca las propiedades en las que utilizan para apuntar a la referenciae, anular (por lo general, querría saber de antemano qué propiedad sería), luego desasignar el referencee.

Cuestiones relacionadas