Pregunta

Estoy mirando algún código (Delphi 7) con la siguiente verificación que se encuentra en la parte superior de cada llamada a un método para un objeto específico:

if not Assigned(self) then
  raise Exception.CreateRes(@sAbstractError);

  { Real code for this method}

Supongo que esto me impediría intentar llamar a un método en un puntero de objeto nulo. Pero obtendría una excepción tan pronto como intentara acceder a los datos de los miembros en ese caso de todos modos, ¿verdad?

¿Es este algún tipo de estándar que nunca había visto antes? El objeto en cuestión deriva de TPersistent.

¿Fue útil?

Solución

Puede llamar a un método de instancia con un puntero nulo, aunque no es el tipo de cosa que desea hacer deliberadamente. Cuando eso sucede, la ejecución continúa bastante feliz hasta que necesita acceder a los datos de la instancia y luego todo se arruina.

En ese caso, la comprobación de cero le alertará en la parte superior del procedimiento para que pueda hacer algo diferente, como registrar un seguimiento de la pila. O puede poner un punto de quiebre en la línea de subida para que pueda sumergirse y ver lo que está sucediendo.

Es decir, es algo que podría hacer si tuviera un error específico que intentara rastrear dónde se usaba una referencia nula.

Hacerlo regularmente me parece un olor a código.

Otros consejos

Un error claro quejándose de un puntero nulo es mejor que una violación de acceso que no dice cómo sucedió.

Hay escenarios de infracción de acceso que pueden conducir a la ejecución de código en la memoria donde Self es nulo. Algunos programadores, en lugar de resolver el problema real, intentan evitar el uso de tales afirmaciones, para evitar corrupciones de algún tipo. Verificaría muy bien si esa Excepción alguna vez surge en tiempo de ejecución, si es así, tienes un código defectuoso en tus manos.

Puedes leer el siguiente artículo sobre el tema: Cuando estás en cero ... sabes Estás en problemas .

Otra posibilidad está relacionada con los eventos, puede leer más aquí, con muchos ejemplos para tales pruebas, y las explicaciones correspondientes: Eventos de multidifusión - Parte 2 .

Esta es una ocasión que definitivamente debería provocar un bloqueo (es decir, una excepción del sistema operativo como "leer desde la dirección 0x00000000"). Lanzar una excepción de idioma es simplemente redundante (y el mal uso de EAbstractError aquí no lo mejora).

Verificar parámetros de entrada válidos no es una tarea factible en un lenguaje inseguro, ya que nunca obtendrá certeza y, por lo tanto, su manejo de parámetros no válidos nunca será consistente. (¿Por qué arroja una excepción cuando se pasa un puntero nulo, pero no para 0x00000001, que es igual de inválido?). Para una discusión más técnica de esta pregunta, lea el blog de Larry Osterman sobre por qué no verificar los punteros válidos .

Se debe tener en cuenta una excepción: en Delphi, el método Gratis se puede invocar en un puntero nulo, que por supuesto requiere ese tipo de comprobación.

Y siempre existe la posibilidad de que el código no se bloquee cuando se ejecuta con nil Self. Ejemplo: si no está accediendo a ningún campo del objeto propietario. En ese caso, esta prueba detectaría el problema que de otro modo no se detectaría.

Aún así, eso lleva la programación defensiva al extremo. Nunca (OK, casi nunca, solo cuando estoy cazando wabbits ... errr ... eliminando errores) hago eso.

Parece que la intención original de ese método es que se convierta en un método abstracto.

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