Pregunta

En este párrafo del uso de constructo delete this C ++ FAQ es discutido. se enumeran 4 restricciones.

Restricciones de 1 a 3 se ven muy razonable. Pero ¿por qué es la restricción 4 allí que "no hay que examinarlo, compararlo con otro puntero, compararlo con NULL, imprimirlo, echarlo, hacer nada con ella"?

Me refiero this es otro puntero. Por qué no puedo reinterpret_cast a un int printf() o llame a la salida de su valor?

¿Fue útil?

Solución

La razón por la que no se puede hacer nada con un puntero después de eliminarla (esto, o cualquier otro puntero), es que el hardware podría (y algunas máquinas antiguas no) trampa de intentar cargar una dirección de memoria no válida en un registro. A pesar de que puede estar bien en todo el hardware moderno, la norma dice que lo único que se puede hacer a un puntero no válido (no inicializado o eliminado), consiste en asignar a la misma (ya sea NULL, o de otro puntero válido).

Otros consejos

El valor de 'esto' después de llamar a borrar no está definido, y el comportamiento de todo lo que haces con él también está definido. Mientras yo esperaría mayoría de los compiladores a hacer algo con sentido, no hay nada (en la especificación) detener el compilador de decidir que su comportamiento en este caso particular se emiten código para dar formato al disco duro. La invocación de un comportamiento indefinido es (casi) siempre es un error, incluso cuando su compilador particular, se comporta de la manera que le gustaría que lo haga.

Se puede evitar esto tomando una copia del puntero (como un entero) antes de llamar a borrar.

Aha!

3.7.3.2/4:." ... la función de cancelación de asignación deberá desasignar el almacenamiento al que hace referencia el puntero, lo que hace todos los punteros no válidos que se refieren a cualquier parte del almacenamiento desasignado El efecto de utilizar un valor de puntero no válido (incluyendo pasándolo a una función de cancelación de asignación) es indefinido".

Tenga en cuenta que esto no dice "con el valor", no "dereferencing el puntero".

Este párrafo no es específico de this, se aplica a cualquier cosa que haya sido eliminado.

ya que cualquier acción que puede tomar con ese puntero podría desencadenar la lógica que se interpreta en los métodos de la clase de ese objeto, lo que podría dar lugar a un accidente.

Ahora, algunas de las acciones que podría ser un punto Lo aparentemente "seguro", pero es difícil decir lo que ocurre dentro de cualquier método que se puede llamar.

Desde el puesto de: "no debe examinarla, compararlo con otro puntero, compararlo con NULL, imprimirlo, echarlo, hacer nada con él"

Todas estas acciones pueden desencadenar funciones relacionadas con el operador, que son evaluados con un puntero definido. Idem para la fundición.

Ahora bien, si se realiza una reintepret_cast, eso es probablemente una historia diferente, y es probable que se llevaba bien con él, como reinterpretar es sólo un poco por la reinterpretación de bits, sin la participación (por lo que yo sé) cualquier llamada al método.

Por la misma razón por la que no se haría con cualquier otra puntero y luego tratar de realizar cualquier operación sobre el mismo.

b / c la dirección que esto se refiere al momento, es indefinido, y no se sabe lo que podría estar allí ...

En un programa multi-hilo, el momento en que delete un puntero, el espacio libre se puede asignar por otro hilo, sobrescribir el espacio utilizado por this. Incluso en un programa de un solo hilo, a menos que seas muy cuidadoso con lo que llama antes de returning, cualquier cosa que haga después delete this podría asignar memoria y sobrescribir lo que solía ser apuntado por this.

En un Microsoft Visual C ++ ejecutable compilado en modo de depuración, deleteing un puntero hace que su memoria para ser sobrescritos inmediatamente con un patrón de prueba 0xCC (variables sin inicializar también se inicializan con este patrón), para ayudar en la identificación colgando errores puntero como este uno.

Esto me recuerda a cuando ha corregido un error en un juego en línea jugable en el que el constructor de un objeto Fuego elimina el más antiguo de fuego si el número total de incendios había alcanzado un determinado número. El fuego fue eliminado a veces el fuego de los padres crear un nuevo fuego - bam, colgando de errores puntero! Fue sólo debido a la suerte de que este error interactuó con el algoritmo de asignación de memoria de una manera completamente predecible (el Fuego eliminada siempre se sobrescribe con un nuevo fuego de la misma manera) - de lo contrario habría causado una desincronización entre los jugadores en línea. He encontrado este error al reescribir la forma en que el juego hizo la asignación de memoria. Debido a su previsibilidad, cuando me fijo, yo también era capaz de poner en práctica la emulación de su comportamiento compatibilidad con los clientes de juego de mayor edad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top