2012-02-14 21 views
11

generalmente suelto el objeto después de su uso por¿Cuál es la necesidad de asignar las negativas después de lanzar un objeto

[myObject release]; 

Pero he encontrado en algunos tutoriales en línea que asignan un nula después de soltar el objeto. Como

[myObject release]; 
myObject = nil; 

¿Es necesario?

+0

posible duplicado de [¿Por qué conjunto de objetos a cero después de enviar el mensaje de liberación en Obj-C] (http://stackoverflow.com/questions/3072003/why-set-object-to-nil-after-sending -release-message-in-obj-c) –

+1

Otros candidatos: [Establecer punteros a nulo después del lanzamiento] (http://stackoverflow.com/q/1418999/) [¿Es necesario configurar los punteros a cero después del lanzamiento] (http://stackoverflow.com/q/803531/) [Cuándo establecer las referencias de objeto a nil] (http://stackoverflow.com/q/1670876/) [Diferencia entre lanzamiento y lanzamiento, luego configurado en nil] (http : //stackoverflow.com/q/2809603/) –

Respuesta

29

Es un debate de larga duración sobre si es necesario establecer el puntero a nil después de soltarlo, pero estoy de acuerdo en que es una buena idea.

Después de que se libera el objeto, el puntero que sostiene apunta hacia el mismo lugar.Si su lanzamiento ha tomado el conteo retenido a 0, entonces el objeto será desasignado. Si luego intenta enviar un mensaje al objeto desasignado, obtendrá un error EXC_BAD_ACCESS. Sin embargo, enviar un mensaje al puntero una vez configurado en nil no generará ningún error; simplemente no hará nada.

La otra cara del argumento es que si está enviando un mensaje a un objeto desasignado, es bueno saberlo y corregirlo para asegurarse de que no ocurra.

Hay personas inteligentes en ambos campos.

+2

+1 para señalar el lado positivo de no hacerlo – Saphrosit

+0

+1 para "personas inteligentes en ambos campos". – mskfisher

3

No, no es estrictamente obligatorio.
Si su código está bien estructurado, no es necesario forzar que myObject sea igual a cero.

Sin embargo, puede ser un buen hábito: release no destruye el objeto inmediatamente, simplemente disminuya el recuento retain. Por lo tanto, puede ser que, incluso si llama a la versión, el objeto seguirá allí por un tiempo, creando problemas si intenta enviar mensajes.

El uso de myObject = nil; elimina este problema, ya que, incluso si envía un mensaje al myObject, nada sucederá en realidad.

+3

Solo puedo añadir esta [gran publicación de blog de Jeff Lamarche] (http://iphonedevelopment.blogspot.com/2010/09/dealloc.html). Que es una lectura interesante. – rckoenes

+0

Si el recuento de retenciones llega a cero en un lanzamiento, el objeto se destruye. Pero la memoria no se borra, por lo que parece que todavía está allí. Solo el valor del puntero se establece en cero. La protección es que si otra parte del código hace referencia a través del puntero y el puntero es nulo, no pasará nada malo, ¡tenga en cuenta que esto cubría un error en el código !. Hay otra posibilidad, asignar (id) 0x42 para que haya un bloqueo inmediato si hay un acceso a través del puntero por error, entonces el código puede ser reparado. – zaph

2

No es obligatorio, pero es sobre todo un problema de estilo. Asignar nil después de la liberación asegura que no se puede usar accidentalmente la referencia liberada nuevamente (lo que puede provocar o no un bloqueo). Simplemente llamando al release en la referencia puede hacer que la memoria subyacente desaparezca. Sin embargo, el puntero seguirá apuntando a la dirección (que ahora es potencialmente no válida), y el resultado de una invocación de método posterior con ese puntero no está definido.

2

No, no es obligatorio.

Es una cuestión de seguridad. Si tiene

[myObject release]; 

y luego en otro lugar hacer

[myObject doSomething]; 

Entonces obtendrá problemas.

Si tiene

[myObject release]; 
myObject = nil; 

y luego en otro lugar lo hace

[myObject doSomething]; 

, no ocurrirá nada porque se está llamando en un objeto nulo. Por lo tanto, su aplicación no se derrumbará en gran cantidad. O si tiene otro lugar en el código

[myObject release]; 

Luego se liberará en un objeto nil y no se liberará en exceso.

¡Obviamente debe evitar invocar un objeto que ya ha liberado!

1

no realmente, pero mejor usarlo para evitar errores ...

si se llama a algún lugar de su myObject código cuando ha sido liberarla le dan un mal error, pero si se stetted a cero el error podrá, mediante bypass

si se intenta:

myObject.someProperty = 1; 

o

if (myObject) {...} 

y acaba de lanzar myObject, solo podría bloquear su aplicación ...

1

No es obligatorio, pero generalmente se considera una buena práctica en todos los entornos, con la excepción de que generalmente se considera innecesario en una -dealloc método.

La razón por la que es común configurar el puntero del objeto en cero después del lanzamiento es porque el asignador de métodos Objective-C no intentará enviar un mensaje a un objeto nil, lo que significa que puede usar el objeto accidentalmente luego.

0

después de lanzar un abject pero no asigna NULL, guarda la dirección pero el contenido se desasigna. Por lo tanto, ahora no apunta a ninguna ubicación de memoria válida. Por ahora, ptr está colgando del puntero, que probablemente tiene una dirección pero no apunta a ninguna ubicación de memoria válida. por lo que es una buena práctica asignar NULL después de liberar la memoria asignada como se detalla a continuación

ptr = NULL;

de esta manera se resolverá el problema colgando.

-2

En un Apple Tech Talk fui a hace un par de años que los ingenieros de Apple discutieron algunas instancias en las que era esencial asignar a cero, pero no puedo recordar los detalles aparte de lo que estaba dentro de dealloc en las instancias discutido. Baste decir que no es correcto decir que nunca tienes que hacerlo o que es una mala práctica hacerlo. A veces tienes que hacerlo. Pero la mayoría de las veces no es necesario. Lo siento, mi memoria no está más clara.

2

Siempre configuraré a nil.

Apple a veces a veces (documentado) comprobar nil.

Ejemplo;

Si establece los navigationItem.titleView necesidades que se establezcan de nuevo a nil si desea volver a utilizar navigationItem.title, o no se mostrarán a su título.

Hay muchas referencias a esta "comprobación nula" en la documentación de Apple.

Referencia;

https://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationItem_Class/Reference/UINavigationItem.html

Restoring navigationItem.title after removing navigationItem.titleView

0

que sugeriría un enfoque híbrido. Veamos los requisitos de aplicaciones típicas:

  1. queremos minimizar aplicación se bloquea en la producción
  2. queremos atrapar a problemas como el acceso a la memoria potencialmente liberado, mientras estamos probando

Una buena solución es asignar de forma condicional a:

  1. Ninguna de las versiones de lanzamiento
  2. Un mal intencionada puntero (p.ej. 0x20) en depuración.

Esto proporciona estabilidad en las compilaciones de producción, pero en el modo de depuración cualquier intento de acceder a la variable bloqueará explícitamente la aplicación. Tenga en cuenta que la ejecución de llamadas en un objeto no garantiza que la memoria del objeto se elimine, por lo tanto, la necesidad de establecer explícitamente en el puntero malo.

#ifdef DEBUG 
    #define RELEASE(obj) [(obj) release]; (obj) = (id)0x20; 
#else 
    #define RELEASE(obj) [(obj) release]; (obj) = nil; 
#endif 
Cuestiones relacionadas