memory management - Explicación del almacenamiento fuerte y débil en iOS5
memory-management automatic-ref-counting (6)
Soy nuevo en el desarrollo de iOS5 y uso Object-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 suenan idénticas a mí 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; que me confunde Luego miro en Open U CS193p, donde distingue entre fuerte y débil:
Fuerte : "mantén esto en el montón hasta que ya no lo apunte más"
Débil : "mantén esto mientras alguien más lo señale fuertemente"
¿Las dos definiciones no son idénticas = si el puntero ya no apunta a un objeto, y luego 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?
¿No son las dos definiciones idénticas?
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 sugerencias para <some_object>
, una fuerte y otra débil. Si establecemos strongObject
en nil
así:
strongObject = nil;
Luego, si sigue las reglas que describió, entonces se hará estas preguntas:
Fuerte: "mantén esto en el montón hasta que ya no lo apunte más"
strongObject
ya no apunta a<some_object>
. Entonces no necesitamos guardarlo.Débil: "mantén esto mientras alguien más lo señale fuertemente"
weakObject
aún apunta a<some_object>
. Pero como nadie más lo señala, esta regla también significa que no es necesario que la conservemos.
El resultado es que <some_object>
está desasignado y si su tiempo de ejecución lo admite (Lion e iOS 5 hacia arriba), entonces weakObject
se establecerá automáticamente en nil
.
Ahora considere lo que sucede si establecemos weakObject
en nil
manera:
weakObject = nil;
Luego, si sigue las reglas que describió, entonces se hará estas preguntas:
Fuerte: "mantén esto en el montón hasta que ya no lo apunte más"
strongObject
apunta a<some_object>
. Entonces necesitamos mantenerlo.Débil: "mantén esto mientras alguien más lo señale fuertemente"
weakObject
no apunta a<some_object>
.
El resultado es que <some_object>
no está desasignado, pero weakObject
será el puntero nil
.
[Tenga en cuenta que todo lo que está asumiendo <some_object>
no está apuntado por otra referencia fuerte en otro lugar / algún otro medio de ser "sostenido"]
Fuerte
- Crea propiedad entre la propiedad y el valor asignado.
- 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.
- Es reemplazo para retener. Usamos si y solo si necesitamos usar como retener.
Débiles
- Crea no propiedades entre la propiedad y el valor asignado.
- Strong se usa en el objeto primario y weak se usa en el objeto hijo cuando se libera el elemento primario, y la referencia del objeto secundario también se establece en nil
- Ayuda a prevenir los ciclos de retención.
- No protege el objeto al que se hace referencia cuando se recolecta el recolector de elementos no utilizados.
- Débil es esencialmente asignado, no retener la propiedad.
La diferencia es que un objeto será desasignado tan pronto como no haya puntos fuertes para él. Incluso si los punteros débiles lo señalan, una vez que el último puntero fuerte desaparezca, el objeto será desasignado, y todos los punteros débiles restantes se pondrán a cero.
Quizás un ejemplo está en orden.
Imagina que nuestro objeto es un perro, y que el perro quiere huir (ser desasignado).
Los indicadores fuertes son como una correa en el perro. Mientras tengas la correa unida al perro, el perro no huirá. Si cinco personas unen su correa a un perro, (cinco punteros fuertes a un objeto), entonces el perro no escapará hasta que las cinco correas estén sueltas.
Los indicadores débiles, por otro lado, son como niños pequeños que señalan al perro y dicen "¡Mira, un perro!" Mientras el perro siga con la correa, los niños pequeños aún pueden ver al perro, y aún así lo señalarán. Sin embargo, tan pronto como todas las correas se separan, el perro huye sin importar cuántos niños pequeños lo señalen.
Tan pronto como el último puntero fuerte (correa) ya no apunta a un objeto, el objeto será desasignado, y todos los punteros débiles se pondrán a cero.
No, no son idénticos sino muy diferentes. Usas fuerte solo si necesitas retener el objeto. Usas weak en cualquier otro caso, con la ventaja de que puedes saber si object ha sido eliminado de heap porque nadie lo está reteniendo.
Otro ejemplo: El estudiante es un Object
, se supone que puede graduarse ( deallocate
) siempre y cuando haya terminado todos los cursos básicos ( strong pointers
), sin importar si toma cursos opcionales ( weak pointers
). En otras palabras: el puntero fuerte es el único factor de desasignación de ese Object
.
Sé que llegué un poco tarde a esta fiesta, pero creo que es importante confundir el problema señalando que el significado de "modelos de memoria fuertes y débiles" depende de si se trata de software o hardware.
Para hardware, débil o fuerte indica si hay compatibilidad con 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 un orden secuencial, y las operaciones de cada procesador individual aparecieran en esta secuencia en el orden especificado por su programa. - Lamport, 1979
WTF tiene que ver con la memoria? Implica que las escrituras en variables por 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 los procesadores con un modelo fuerte, que somos todos nosotros porque x86 y x64 tienen un modelo fuerte, esta es una trampa terrible. Usar un bool para señalar otro hilo para salir funciona bien en un modelo fuerte. El mismo código en Arm no funciona en absoluto a menos que marques el flag como volátil, e incluso entonces es errático.
Si bien es cierto que Arm8 + lo cambia completamente con soporte explícito para adquirir / liberar, 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 actualicen.
Para un examen extenso de este tema, lo remito a la inimitable Herb Sutter .