Estoy aprendiendo C++ y la lectura de C++ de la Cartilla. Hay una pregunta que me gustaría saber la respuesta:

Dado un puntero p, se puede determinar si p apunta a un objeto válido? Si es así, ¿cómo? Si no, ¿por qué no?

  • Por favor defina «válido».
  • Precisamente lo que los punteros inteligentes que son buenas.
  • si usted sabe cómo la memoria subyacente gerente de obras (cómo lo hace su libro de mantenimiento), entonces tal vez podría averiguar. Sin embargo, esto sería muy específicas de la plataforma. Si usted administrar la memoria por sí mismo, que no debería ser un problema. El mejor curso de acción es todavía adhieren a las mejores prácticas (RAII, encapsulación).
  • lo de punteros inteligentes que son buenas. Pero GIGO se aplica todavía; siempre se puede crear puntero inteligente que contiene un puntero erróneo.
  • Bueno, sí, pero si se usan correctamente y a fondo para administrar su memoria, no deberías tener ese problema. Como para las cosas sin asignación dinámica, pierde un poco de valor en ese sentido.
  • relee tu comentario, pensando en bruto «punteros» en lugar de «punteros inteligentes», y dice la misma cosa. Punteros inteligentes son una herramienta, no una solución en sí mismos.
  • Posibles duplicados de Pruebas de punteros para la validez (C/C++)

InformationsquelleAutor 2013Asker | 2013-06-19

6 Comentarios

  1. 36

    No, No puede. Por qué? Porque sería muy costoso mantener la meta de datos acerca de lo que constituye un puntero válido y lo que no, y en C++ no se paga por lo que usted no quiere.

    Y no quiere para comprobar si un puntero es válido, porque saber donde un puntero viene, ya sea porque es una parte privada de su código de control, o porque haya especificado en su la cara externa de los contratos.

    • Yo diría que es realmente no es caro… Con los punteros inteligentes que ahora son parte de la biblioteca estándar, hay una cantidad muy mínima de sobrecarga. En la gran mayoría de los casos de uso el beneficio es mucho mayor que el costo. Ver un post relacionados para obtener más información: stackoverflow.com/questions/22295665/…
    • Que parece demasiado simplista y poco realista. Punteros inteligentes tienen diferentes semántica y, por tanto, no son comparables (unique_ptr, shared_ptr), o que tienen la misma semántica y también los mismos problemas (observer_ptr). Tenga en cuenta también que unique_ptr en la práctica es más caro que un raw puntero cuando se utiliza como un tipo de retorno debido a la mala ABI opciones (que no se devuelve en los registros).
    • No estoy diciendo que ellos no tienen un costo. Todo lo que estoy diciendo es que si no estás trabajando en un entorno integrado y la escritura de código para un microprocesador con memoria limitada y una lenta velocidad de reloj el costo es esencialmente insignificante en comparación con los beneficios en casi todos los casos de uso.
    • Aparte del hecho de que no son reales, las grandes lineas de codificación que lamento es innecesario el impacto en el rendimiento de unique_ptr (en un nivel en el que se incurre en el real valor en dólares de coste), también se ha ignorado mi punto principal: Los punteros inteligentes no son una gota en el reemplazo, ya que tienen diferentes semántica. No hay ninguna obvio puntero inteligente, decir, que realmente podría usar para los no-propiedad-la transferencia de referencia semántica que se correspondería con la semántica de un raw puntero; que requeriría un diseño diferente.
  2. 12

    No es posible. Creo que de este escenario.

    int *ptr = new int(10);
    int *ptrDup = ptr;
    
    delete ptr;

    Pero ptrDup todavía apunta a la posición de memoria apuntada por ptr que ya no existe. Así, deferencing ptrDup los resultados de un comportamiento indefinido. Pero no es el recuento de referencias, lo cual es totalmente un concepto diferente.

    • En realidad, eliminar no toque ptr en sí, por lo ptr, también, todavía señala que la misma memoria y eliminar también se UB…
  3. 7

    No es realmente posible para ver si un puntero es «válida» en todos sus significados.

    Seguro, usted puede tratar de eliminar la referencia del puntero (*ptr = x; o x = *ptr). Si el código no choque, el puntero que apunta a la memoria válida. Si se estrelló, obviamente, el puntero no es bueno. Por desgracia, este enfoque es un poco como la comprobación de si el arma está cargada por el disparo en la cabeza – que no es el más inteligente… por Desgracia, con los punteros, no hay una «comprobación de la cámara para ver si se carga», así que no hay verdadera buena manera de averiguar si el puntero es válida, otros que «si no causa un fallo de hardware, es válido».

    Tenga en cuenta que esto sólo decirte que «es el puntero que apunta a la memoria se puede acceder» en la mayoría de los casos. Esto NO significa que el puntero «es correcto para lo que usted quiere que sea» (por ejemplo, se señala el tipo correcto). Y CIERTAMENTE no le dirá si el puntero apunta a la «vieja data» (es decir, cuando un puntero ERA válida, pero ahora es la memoria utilizada para algo más).

    Por desgracia, con la 232 o 264 [en realidad 248] posiblemente válido de direcciones de memoria en un sistema moderno, es casi imposible saber qué direcciones son válidas y cuáles no lo son. Incluso dentro del sistema operativo, la forma en que el sistema operativo se encarga de determinar si se puede escribir en la memoria a la que le pidió que escribir es «tratar de escribirlo, a ver qué pasa». Para el sistema operativo, este funciona muy bien, porque puede ser cuidadosos acerca de «esto puede ir mal, y si lo hace, yo voy a seguir por ahí en el código de recuperación de errores». El sistema operativo tiene que lidiar con este porque tiene que aceptar, a) que los programadores cometen errores, y b) que algunas personas escriben código malicioso para INTENTAR romper el sistema operativo.

    La forma de una aplicación para «asegurarse de que los punteros son válidos» es que el programador escribe el código que es muy CUIDADOSO acerca de lo que se almacena punteros, cómo se libera a los punteros, y sólo el uso de punteros que tienen valores válidos que en ellos se almacenan. Usted no debe terminar «tener que comprobar si el puntero es válido», está «haciendo el mal».

    (Cuando se trabaja con un sistema por un tiempo, y la lectura de los valores de puntero en un depurador, que hacer después de un tiempo de reconocer las «buenas» y «malas» punteros – pero eso es sólo porque usted aprenda lo que, por lo general, un buen indicador de frente a una mala puntero parece. Escribir código para reconocer tal es casi imposible, especialmente si el sistema está asignando una gran cantidad de memoria, por lo que utiliza la mayoría del espacio disponible.)

    De curso, en C++, hay punteros inteligentes, vectores, y varias otras herramientas que significa un montón de tiempo que usted incluso no tiene que molestarse con los punteros. Pero la comprensión de cómo el uso de punteros y cómo punteros de trabajo es todavía una buena cosa que hacer.

    • Si usted derefence un puntero-a-T que no apunta a un objeto de tipo T, el comportamiento es indefinido, por lo tanto su declaración de apertura es falso – es posible que no se bloquee.
    • Ok, he añadido una declaración a ese efecto. Mi idea principal era realmente de que «si usted tiene un mal puntero (no válido, en lugar de apuntar al tipo equivocado), es difícil encontrar que fuera sin que se caiga».
    • No estoy convencido de que los primeros párrafos de esta respuesta añadir nada útil el post. Especialmente desde que la pregunta es acerca de si un puntero apunta a un «objeto válido», no «de memoria válida». Un puntero no válido es a menudo un puntero que era válido hasta el usuario llamado delete, en cuyo caso se puede «mirar» correcta, y parece funcionar, pero en realidad retorno zombie basura, que sólo pasa a situarse dentro de la memoria válida gama de su aplicación. Así, con todos estos defectos, quizá es mejor dejarlo en «No», seguido por cómo evitar tener que comprobar la validez de un raw puntero?
    • Ok, he añadido una «primera frase» para decir «No, No puedes».
    • Que en realidad es suficiente de una mejora para mi gusto. +1
  4. 4

    Si un puntero se establece en nullptr, que significa que no se ha dado un objeto a punto y en su lugar se le ha dado un valor «predeterminado». Es posible que el puntero podría no ser asignado a nullptr y al mismo tiempo no ser asignado a un objeto válido, pero en ese caso sería imposible determinar que. 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)
  5. 2

    Como se indica en otras respuestas, esto no es posible con una cruda puntero de la forma SomeObject* somePointer. Sin embargo, c++11 introdujo un nuevo conjunto de administración de memoria dinámica y los nuevos punteros inteligentes. El uso de un puntero inteligente puede detectar si el recurso está disponible todavía. Por ejemplo, en las siguientes:

    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.

    Leer más acerca de std::shared_ptr y std::weak_ptr para más ejemplos. Antes de c++11 equivelent tipos de punteros inteligentes están disponibles en aumentar.

    • Punteros inteligentes son (mucho) mejor en C++11, pero se introdujeron mucho antes de que…
    • Voy a añadir la palabra nueva, pero yo realmente no quiero hablar de auto_ptr aquí porque necesito una página de por qué no usarla. Voy a añadir una nota acerca de impulsar así.
  6. -1

    El C++ especificación no nos da ningún tipo de soporte para determinar si un puntero es válido. El mejor es el uso de punteros inteligentes porque son mucho menos propensos a hacer uso indebido de ellos (tienen varios guardias de permitir la apropiada manipulación).

    Sin embargo, varias empresas que desarrollan las bibliotecas y herramientas para agregar código para comprobar cada de acceso a la memoria y si uno no es válido, se obtiene una interrupción.

    Con g++, yo uso el desinfectante opciones como:

    g++ -fsanitize=address -fsanitize=enum -fsanitize=unreachable ...

    La primera proteger sus accesos a la memoria a un punto donde tratando de usar el puntero equivocado va a ser detectada con un SEGV. Utiliza la MMU para proteger su memoria por lo que es impulsada por hardware. Se ralentiza el código, pero todavía bastante rápido. Una cosa a tener en cuenta en este modo, los archivos binarios asignar 2 tb de memoria virtual. Usted no quiere correr demasiado muchos de esos binarios simultáneamente, a menos que usted tiene un montón de memoria RAM.

    Como una nota al margen: es la parte del código viene de Google y la primera aplicación fue en clang.

    En directo de C/C++ bajo Linux, usted puede comprobar si un puntero está dentro de su proceso. Sin embargo, con la gran ayuda de la memoria, que no se tiene que tomar la pila en cuenta también. El inicio puntero es algo así como 0 x 400000. La dirección final de la pila puede ser determinada utilizando sbrk(). Por lo que su montón de punteros debe estar entre esos dos límites.

Dejar respuesta

Please enter your comment!
Please enter your name here