2011-02-21 14 views
6

Bastantes de las personas parecen utilizar una macro como¿Realmente necesitamos una macro de liberación segura?

#define SAFE_RELEASE(X) [X release]; X = nil; 

(yo incluido).

He estado reevaluando por qué lo estoy usando y quería ponerme al frente de alguna opinión.

El propósito (creo) para el uso de esta macro es para que si tuviera que accidentalmente utilizar su objeto después de soltarlo, entonces no obtendrá una mala excepción acceso debido a Objective-C será bastante fácilmente ignorarlo cuando el objeto es nulo.

Me parece que esto tiene el potencial de enmascarar algunos errores desconocidos. Tal vez sería preferible que el programa se bloquee cuando intente usar X nuevamente. De esa forma, durante la prueba, puede encontrar el problema y mejorar el código.

¿Este macro alienta la programación perezosa?

¿Pensamientos?

+1

La sección correspondiente del [FAQ] (http://stackoverflow.com/faq) para las preguntas que no deben plantearse aquí. - 'no hay un problema real que deba resolverse:' 'Siento curiosidad si otras personas sienten lo mismo que yo' ". – Abizern

+0

Lo suficiente, pero es un problema que estoy enfrentando. El problema es si debería continuar usando esta macro? ¿Hay alguna buena razón para usarlo de lo que no estoy enterado? – Ian1971

Respuesta

6

Creo que hablas de todos los pros y los contras de tu pregunta, por lo que no tengo que añadir una cantidad enorme. Personalmente no uso la construcción. Como sugiere, se puede usar para empapelar áreas donde las personas no entienden la administración de la memoria correctamente. Mi preferencia es corregir el error y no el síntoma.

Sin embargo, un compromiso que he visto de vez en cuando es:

  • hacer que se cierre durante el desarrollo
  • ¿Tienen el var = nil; en el código de producción

De esa manera fuerza ser más confiable con los clientes que pagan y aún se bloquea temprano durante el desarrollo.

No estoy interesado en esto tampoco, ya que está usando un código diferente para sus usuarios y simplemente porque la versión buggy sigue funcionando no significa que está haciendo lo correcto. No estropear, pero corromper su base de datos no es un comportamiento deseable ...

+0

Acepto que no me gusta tener un código diferente en producción – Ian1971

+0

¿Por qué votar abajo? –

1

No necesita necesita, pero es útil tener. Uso algo similar en mis aplicaciones. Puedes considerarlo "flojo", pero cuando tienes alrededor de 20 objetos, escribirlos manualmente es tedioso.

+1

Supongo que no se trata tanto del macro per se sino de la teoría de establecer un objeto como nulo una vez que lo liberas. Si ha terminado con el objeto, entonces tal vez no debería intentar volver a acceder a él, y si lo hace nuevamente, entonces es mejor tener el bloqueo para poder resolver ese problema de código en particular. es decir, ¿por qué intentas acceder de nuevo? – Ian1971

2

Creo que, o un equivalente como self.myVar = nil en su caso, es un bien. Hay muchos casos en los que simplemente no puede asignar cero y asumir que cualquier acceso posterior es un error.

Por ejemplo, en UIKit es un buen comportamiento liberar tantos recursos como sea posible cuando el sistema operativo se lo pida. P.ej.

- (void)didReceiveMemoryWarning 
{ 
    [myCachedData release]; 
    [super didReceiveMemoryWarning]; 
} 

Ahora, cuando se utiliza mi clase a continuación, ¿cómo puedo saber que myCachedData ahora no es válido? La única forma (salvo que otra variable actúe como indicador) es establecer myCachedData en nil después de soltarlo. Y condensar esas dos líneas tediosas en una es exactamente para lo que es SAFE_RELEASE.

+0

Creo que tiene razón; es correcto establecerlo en cero cuando corresponda. Creo que la trampa en la que caí estaba usando ciegamente el macro y no pensaba mucho en eso. – Ian1971

1

Estaba buscando la misma pregunta.Con el bit de lectura que hice sólo tengo algo como esto:

#define DEBUGGING 
    //#define PRODUCTION 

#ifdef DEBUGGING 
#define SAFE_RELEASE(X) [X release]; 
#else 
#define SAFE_RELEASE(X) [X release]; X = nil; 
#endif 

Así que de esa manera si estoy desarrollando, consigo los choques. En producción, no.

de Scott < -

+0

Esto podría llevar a rastrear errores en la producción: vea mi respuesta para más detalles. – Sebastian

1

Como se señaló Andrew, hay casos en que la asignación de nil no sólo es evitar errores, pero es necesario. Sólo considere típica UIViewController código

- (void)viewDidLoad { 
    button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // autoreleased 
    [button retain]; // keep alive 
} 

- (void)viewDidUnload { // view has been removed 
    [button release]; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- problem 
} 

En caso de que se carga el controlador, después descargada (porque se muestra otra vista controlador una memoria está baja) y finalmente destruida, el [button release] en dealloc se sobre-suelte el botón (enviar un mensaje a un objeto liberado). Por lo tanto, es necesario asignar nil. La solución segura sería:

- (void)viewDidUnload { // view has been removed 
    [button release]; 
    button = nil; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- safe 
} 

Para esos casos, una macro es agradable y útil. Para ser más explícitos acerca de lo que hace, nombre mejor que RELEASE_AND_NIL

#define RELEASE_AND_NIL(X) [X release]; X = nil; 
Cuestiones relacionadas