c++ - punteros - que es puntero this
C++ ¿Es posible determinar si un puntero apunta a un objeto válido? (5)
Estoy aprendiendo C ++ y leyendo C ++ Primer. Hay una pregunta que me gustaría saber la respuesta:
Dado un puntero p , ¿puede determinar si p apunta a un objeto válido? ¿Si es así, cómo? ¿Si no, porque no?
Gracias.
Como se indicó en otras respuestas, esto no es posible con un puntero en bruto de la forma SomeObject* somePointer
. Sin embargo, c++11
introdujo un nuevo conjunto de gestión de memoria dinámica y nuevos punteros inteligentes . Usando un puntero inteligente puede detectar si el recurso todavía está disponible. Por ejemplo en el siguiente:
std::weak_ptr<int> w; // Our pointer to a resource.
{
std::shared_pointer<int> s = std::make_shared<int>(5); // The resource.
w = s; // We can set the weak pointer to the shared pointer.
auto s2 = w; // Here we can promote the weak pointer to a shared pointer to control
// the resource.
*s2 = 6; // Here we can use the resource.
} // Here the resource is destroyed.
auto s2 = w; // Here we will fail to get the resource because it has been destroyed. We
// have successfully used smart pointers to detect if the resource exists.
Lea más sobre std::shared_ptr y std::weak_ptr para más ejemplos. Antes de c++11
hay disponibles diferentes tipos de punteros inteligentes en boost
.
Imposible. Piensa en este escenario.
int *ptr = new int(10);
int *ptrDup = ptr;
delete ptr;
Pero ptrDup
todavía apunta a la ubicación de memoria apuntada por ptr
que ya no existe. Por lo tanto, ptrDup
da ptrDup
resultado un comportamiento indefinido. Pero hay un recuento de referencias que es un concepto totalmente diferente.
No es realmente posible ver si un puntero es "válido" en todos sus significados.
Claro, puedes intentar eliminar la referencia al puntero ( *ptr = x;
o x = *ptr
). Si su código no falla, el puntero está apuntando a una memoria válida. Si se estrelló, obviamente, el puntero no es bueno. Desafortunadamente, este enfoque es un poco como verificar si una pistola está cargada disparándola a la cabeza, lo cual no es lo más inteligente ... Desafortunadamente, con los punteros, no hay "revisar la cámara para ver si está cargada", así que no es una buena forma de averiguar si un puntero es válido, excepto "si no causa un fallo de hardware, es válido".
Tenga en cuenta que esto solo le dirá que "el puntero está apuntando a alguna memoria a la que puede acceder" en la mayoría de los casos. NO significa que el puntero "es correcto para lo que quiere que sea" (por ejemplo, apunta al tipo correcto). Y CIERTAMENTE no te dirá si el puntero está apuntando a "datos obsoletos" (es decir, cuando un puntero era válido, pero ahora se usa la memoria para otra cosa).
Desafortunadamente, con 2 32 o 2 64 [en realidad 2 48 ] posiblemente direcciones de memoria válidas en un sistema moderno, es casi imposible saber qué direcciones son válidas y cuáles no. Incluso dentro del sistema operativo, la forma en que el sistema operativo se da cuenta de si puede escribir en la memoria a la que le pidió que escribiera es "intentar escribirlo, ver qué pasa". Para el sistema operativo, esto funciona bien, porque puede tener cuidado con "esto puede ir mal, y si lo hace, continuaré allí en el código de recuperación de error". El sistema operativo tiene que lidiar con esto porque tiene que aceptar, a) que los programadores cometen errores, yb) que algunas personas realmente escriben códigos maliciosos para INTENTAR para romper el sistema operativo.
La forma en que una aplicación "se asegura de que los punteros son válidos" es que el programador escriba un código CUIDADO sobre lo que almacena en los punteros, cómo libera esos punteros y solo usa punteros que tienen valores válidos almacenados en ellos. No debe terminar "tener que comprobar si el puntero es válido", entonces está "haciéndolo mal".
(Cuando trabajas con un sistema por un tiempo y lees valores de puntero en un depurador, después de un rato reconoces los punteros "buenos" y "malos", pero eso es solo porque aprendes qué, generalmente, un buen puntero contra un el puntero malo parece. Escribir un código para reconocerlo es casi imposible, especialmente si el sistema está asignando una gran cantidad de memoria, por lo que utiliza la mayor parte del espacio disponible.
Por supuesto, en C ++, hay punteros inteligentes, vectores y varias otras herramientas que significan que muchas veces ni siquiera tiene que molestarse con los punteros. Pero entender cómo usar los punteros y cómo funcionan los punteros sigue siendo algo bueno.
No, no puedes. ¿Por qué? Porque sería costoso mantener los metadatos sobre lo que constituye un puntero válido y lo que no, y en C ++ no pagas por lo que no quieres.
Y no desea verificar si un puntero es válido, porque sabe de dónde proviene un puntero, ya sea porque es una parte privada de su código que controla o porque lo especificó en sus contratos externos.
Si un puntero se establece en nullptr
, eso significa que no se le ha dado un objeto para que apunte y en su lugar se le ha dado un valor "predeterminado". Es posible que el puntero no se pueda asignar a nullptr
y al mismo tiempo no se asigne a un objeto válido, pero en ese caso sería imposible determinarlo. Por ejemplo:
Con nullptr
:
int *ptr = nullptr;
// check if pointer is unassigned to an object
if (ptr == nullptr) ptr = new int{0};
Sin nullptr
:
int *ptr;
// using ptr while uninitialized is Undefined Behavior!
if (ptr != &some_object)