Explicación de almacenamiento fuerte y débil en iOS5


114

Soy nuevo en el desarrollo de iOS5 y uso objetivo-c. Tengo problemas para entender la diferencia entre almacenamiento fuerte y débil . He leído la documentación y otras preguntas de SO, pero todas me suenan idénticas sin más información.

Leí la documentación: Transición a ARC : hace referencia a los términos de retención, asignación y publicación de iOS4; lo que me confunde. Luego miro a Open U CS193p, donde diferencia lo fuerte y lo débil:

Fuerte : "mantén esto en el montón hasta que ya no lo señale"
Débil : "mantén esto mientras alguien más lo señale con fuerza"

¿No son las dos definiciones idénticas = si el puntero ya no apunta a un objeto, entonces libera la memoria que contiene el objeto? Entiendo el concepto de punteros, montón, asignación o desasignación de memoria, pero ¿cuál es la diferencia entre fuerte y débil?


El modelo de gestión de memoria sigue siendo relevante aunque esté utilizando ARC. Aún debe comprender el recuento de referencias, simplemente no tiene que hacerlo manualmente. Entonces, su último párrafo es una demanda irrazonable.
jrturton

Respuestas:


509

La diferencia es que un objeto se desasignará tan pronto como no haya indicadores sólidos hacia él. Incluso si los punteros débiles apuntan a él, una vez que el último puntero fuerte desaparezca, el objeto se desasignará y todos los punteros débiles restantes se pondrán a cero.

Quizás un ejemplo sea apropiado.

Imagine que nuestro objeto es un perro y que el perro quiere huir (ser desasignado).

Los indicadores fuertes son como una correa para el perro. Mientras tenga la correa atada al perro, el perro no huirá. Si cinco personas atan su correa a un perro (cinco punteros fuertes a un objeto), entonces el perro no se escapará hasta que las cinco correas estén sueltas.

Los punteros débiles, por otro lado, son como niños pequeños señalando al perro y diciendo "¡Mira! ¡Un perro!" Mientras el perro todavía esté con la correa, los niños pequeños aún pueden ver al perro y aún lo señalarán. Sin embargo, tan pronto como se quitan todas las correas, el perro huye sin importar cuántos niños pequeños lo señalen.

Tan pronto como el último puntero fuerte (correa) ya no apunte a un objeto, el objeto se desasignará y todos los punteros débiles se pondrán a cero.


2
Se basa en una analogía que Malcom Crawford en Apple dio hace unos años. No sé de dónde lo sacó.
BJ Homer

Recuerdo haber leído algo similar (prearco) en un libro, creo que era Hillegass, pero luego podría haberlo sacado de otro lugar ... ¡aunque es bueno!
jrturton

14
+1 excelente ejemplo. es un derivado del ejemplo de Hillegass sobre cómo se retienen / sueltan las correas, pero me encanta esta adaptación para fuerte / débil.
Dave DeLong

2
@DaveDeLong: Bueno, son ilegales en 10.6 con ARC. No puedes usarlos en absoluto. Así que ese es un punto irrelevante.
BJ Homer

5
Otro bueno son los globos de helio: mientras se sostenga al menos una cuerda, no se irá flotando. Las analogías correa / globo también son buenas para hacer que la gente olvide que la "propiedad" se gestiona mediante retención / liberación.
Steve Weller

34

¿No son idénticas las dos definiciones?

Absolutamente no. La diferencia clave en las dos definiciones que ha señalado es "siempre que alguien más". Es el "otro" lo que es importante.

Considera lo siguiente:

__strong id strongObject = <some_object>;
__weak id weakObject = strongObject;

Ahora tenemos dos punteros para <some_object> , uno fuerte y otro débil. Si nos fijamos strongObjecten nileste modo:

strongObject = nil;

Luego, si sigue las reglas que describió, se hará estas preguntas:

  1. Fuerte: "mantén esto en el montón hasta que ya no lo señale"

    strongObject no apunta a <some_object> más. Entonces no necesitamos quedárnoslo.

  2. Débil: "mantén esto mientras alguien más lo señale con firmeza"

    weakObjecttodavía apunta a <some_object>. Pero como nadie más lo señala, esta regla también significa que no es necesario que la cumplamos.

El resultado es que <some_object>se desasigna y si su tiempo de ejecución lo admite (Lion e iOS 5 en adelante) weakObject, se configurará automáticamente en nil.

Ahora considere lo que sucede si nos fijamos weakObjecta nileste modo:

weakObject = nil;

Luego, si sigue las reglas que describió, se hará estas preguntas:

  1. Fuerte: "mantén esto en el montón hasta que ya no lo señale"

    strongObjectapunta a <some_object>. Así que necesitamos mantenerlo.

  2. Débil: "mantén esto mientras alguien más lo señale con firmeza"

    weakObjectno apunta a <some_object>.

El resultado es que <some_object>se no se cancela la asignación, pero weakObjectserá el nilpuntero.

[Tenga en cuenta que todo lo que se supone <some_object>no está señalado por otra fuerte referencia en otro lugar / algún otro medio de ser "retenido"]


1
Entonces, la principal diferencia entre fuerte y débil es que la desasignación de objetos apuntados con fuerza anulará automáticamente todos los punteros débiles relacionados. Y para que un puntero débil apunte a algo, siempre existe un puntero fuerte. Si es así, ¿se debe apuntar fuertemente al objeto principal de la aplicación?
KMC

Para que un puntero débil apunte a algo válido, entonces sí, debe haber un puntero fuerte. Agregue a eso el hecho de que iOS 5 y Lion admiten el llenado automático de referencias débiles y obtendrá lo que dice. Sin embargo, el tiempo de ejecución de iOS 4 no lo admite. ¿El "objeto principal de la aplicación" supongo que te refieres al UIApplicationobjeto? Eso será fuertemente referenciado por el funcionamiento interno de UIKit, pero no necesita preocuparse por eso.
mattjgalloway

Creo que puedes usar la palabra like como "strongObjectPointer" en lugar de "strongObject". Así que las personas nuevas en la programación tendrán un mejor significado. Buena captura en @BJ Homer post Mr.Matt.Interesting :)
Vijay-Apple-Dev.blogspot.com

2

Fuerte

  1. Crea propiedad entre la propiedad y el valor asignado.
  2. Esto es predeterminado para la propiedad del objeto en ARC, por lo que no le permite preocuparse por el recuento de referencias y liberar la referencia automáticamente.
  3. Es un reemplazo para retener. Usamos si y solo si necesitamos usar como retener.

Débiles

  1. Crea no-propietarios entre la propiedad y el valor asignado.
  2. Strong se usa en el objeto principal y débil se usa en el objeto secundario cuando se libera el padre, entonces la referencia del objeto secundario también se establece en nil
  3. Ayuda a prevenir los ciclos de retención.
  4. No protege el objeto al que se hace referencia cuando lo recolecta el recolector de basura.
  5. Débil es esencialmente propiedad asignada, no retenida.

Vale la pena mencionar aquí cuál es normalmente el ciclo de retención. Tenemos dos objetos: el objeto A y el objeto B. El objeto A tiene una fuerte referencia al objeto B y el objeto B tiene una fuerte referencia al objeto A. Nada más tiene una fuerte referencia al objeto A o B.
boro

2

Otro ejemplo: El estudiante es un Object, se supone que puede graduarse ( deallocate) siempre que haya terminado todos los cursos básicos ( strong pointers), sin importar si toma cursos opcionales ( weak pointers). En otras palabras: un puntero fuerte es el único factor de desasignación de eso Object.


1

No, no son idénticos sino muy diferentes. Use fuerte solo si necesita retener el objeto. Se usa débil en cualquier otro caso, con la ventaja de que puede saber si el objeto se ha eliminado del montón porque nadie lo retiene.


1

Sé que llego bastante tarde a esta fiesta, pero creo que es importante confundir el tema señalando que el significado de "modelos de memoria fuerte y débil" depende de si se habla de software o hardware.

Para hardware, débil o fuerte indica si hay soporte para la coherencia secuencial.

[SC significa que] ... el resultado de cualquier ejecución es el mismo que si las operaciones de todos los procesadores se ejecutaran en algún orden secuencial, y las operaciones de cada procesador individual aparecen en esta secuencia en el orden especificado por su programa. - Lamport, 1979

WTF, ¿eso tiene que ver con la memoria? Implica que las escrituras en variables de diferentes procesadores deben ser vistas en el mismo orden por todos los procesadores. En hardware con un modelo fuerte esto está garantizado. En hardware con un modelo débil, no lo es.

Las respuestas existentes interpretan la pregunta solo en términos de modelos de memoria de software. El hardware no es irrelevante para la programación. Esta misma pregunta menciona iOS, que normalmente se ejecuta en procesadores Arm7. Arm7 tiene un modelo de memoria débil. Para los programadores acostumbrados a procesadores con un modelo sólido, que somos todos porque x86 y x64 tienen un modelo sólido, esta es una trampa terrible. Usar un bool para señalar a otro hilo para salir funciona bien en un modelo fuerte. El mismo código en Arm no funciona en absoluto a menos que marque la bandera como volátil, e incluso entonces es errático.

Si bien es cierto que Arm8 + cambia esto por completo con soporte explícito para adquisición / lanzamiento, el software heredado no usa este soporte. El software heredado incluye los tres sistemas operativos del teléfono y todo lo que se ejecuta en ellos, así como compiladores y bibliotecas hasta que se actualizan.

Para un examen más extenso de este tema, le remito al inimitable Herb Sutter .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.