Ubicación de almacenamiento y gestión de memoria de bloques de bloques en iOS

I. Introducción:

 Block es una característica poderosa en Objective-C. Block se puede considerar como la realización de la función de cierre en OC. En esencia, Block también es un objeto ~

 

2. Área de asignación de memoria:

Las principales áreas de asignación de memoria en OC: incluyendo área de pila, área de pila, área constante, área estática global, área de texto (área de código)

 

Área de asignación de memoria

Área de pila: almacena valores de parámetros de función, variables locales, direcciones de retorno de función, etc. Cada vez que llamamos a una función, realizaremos una operación de pila (verá un montón de pilas de llamadas de función en el panel izquierdo de XCode). Se caracteriza por una alta eficiencia de acceso y una estructura de acceso continuo, pero el espacio es pequeño Hay un espacio de direcciones para que el sistema asigne y administre la pila.

Área de montón: esta es el área de memoria en la que los desarrolladores debemos enfocarnos, porque la administración de memoria generalmente proviene de esta área. El efecto desencadenado por malloc, alloc, copy (copia profunda), nuevos y otros métodos es asignar memoria en el área del montón. En el entorno ARC, el sistema nos ayuda a gestionar la asignación de memoria y la liberación de esta área en función del recuento de referencia del objeto, pero siempre debemos prestar atención al uso de memoria en esta área; y en el entorno MRC, los desarrolladores deben estar constantemente Preste atención al uso de la memoria en esta área, de lo contrario, conoce las consecuencias ~

Área estática: esta área en realidad se subdivide en área de datos y área BSS. El área de datos almacena variables estáticas y variables globales que se han inicializado, mientras que el área BSS almacena variables estáticas y variables globales que no se han inicializado, y el sistema es responsable de la liberación y asignación.

Área constante: almacena constantes, liberadas y asignadas por el sistema.

Área de código (área de texto): almacenar el código del cuerpo de la función.

 

3. Tres categorías de Bloque:

Bloque en el área global: __NSGlobalBlock__;

Bloque en el área de la pila: __NSStackBlock__;

Bloque en el área del montón: __NSMallocBlock__;

1 、__NSGlobalBlock__ :

Cuando declaramos un bloque, si el bloque no captura variables externas, entonces el bloque se ubica en el área global.En este momento, las operaciones de retención, copia y liberación de NSGlobalBlock no son válidas. Esto es cierto tanto en entornos ARC como MRC.

 

Como se muestra en la figura, declare y defina un bloque en el área global

2 __ __NSStackBlock__ :

  Alguien puede preguntar aquí, rara vez encuentra bloques ubicados en el área de la pila al programar, ¿por qué? Porque en el entorno ARC, cuando declaramos y definimos un bloque, y no se agregan modificadores adicionales al bloque (el predeterminado es el modificador fuerte), si el bloque captura variables externas, hay esencialmente un bloque de __NSStackBlock__ El proceso de cambio a __NSMallocBlock__ es solo que el sistema nos ayudó a completar la operación de copia, migrando el bloque en el área de la pila al área del montón y extendiendo el ciclo de vida del bloque. Para el bloque de pila, el bloque de pila se recuperará cuando la función salga.

   Entonces, ¿ cuándo aparecerá __NSStackBlock__ en el entorno ARC ? Si usamos el modificador __weak o __unsafe__unretained al declarar un bloque, el sistema no hará la operación de copia por nosotros y no lo migrará al área del montón. Experimentemos:

 

Como se muestra en la figura anterior, myBlock1 modificado por __weak captura la variable externa ny se convierte en un bloque en el área de la pila

 

En el entorno del modificador predeterminado, el bloque que captura las variables externas se encuentra en el área del montón

Podemos ejecutar manualmente el método de copia para verificar la conversión implícita realizada por el sistema por nosotros:

 

Como se muestra en la figura, después de ejecutar manualmente el método de copia, el bloque se migra al área del montón

3 、__NSMallocBlock__ :

En el entorno MRC, necesitamos llamar manualmente al método de copia para migrar el bloque al área del montón. En el entorno ARC, el bloque __ strong modificado (predeterminado) se ubicará en el área del montón siempre que capture variables externas. NSMallocBlock admite la retención y liberación. El recuento de referencia será +1 o -1. Declare y defina el bloque ubicado en el área del montón como se muestra en la figura anterior.

 

Cuatro, bloquear el acceso a diferentes tipos de variables externas:

1. Como todos sabemos, para las variables externas capturadas por el bloque, el bloque se copia a su estructura de datos para lograr el acceso por defecto, por lo que las variables externas comunes capturadas por el bloque no se pueden modificar. Necesitamos cambiar la dirección de memoria de la variable externa, es decir, usar el modificador __block para migrar la dirección de memoria del puntero de la variable externa en la pila al área del montón. ¿Por qué está diseñado así? Citemos una oración de @ChenYiLong:

El diseño de Apple de esta manera debe tener en cuenta la particularidad de los bloques. Los bloques también pertenecen a la categoría de "funciones". Las variables que ingresan a los bloques en realidad han cambiado su alcance. Al cambiar entre varios ámbitos, si no se agregan tales restricciones, la capacidad de mantenimiento de las variables se reducirá en gran medida. Por otro ejemplo, quiero declarar una variable con el mismo nombre que una variable externa en el bloque. ¿Está permitido o no? Solo con tales restricciones se puede realizar tal escenario. Entonces, el área de la pila se convierte en un área de luz roja y el área de la pila se convierte en un área de luz verde.

Por lo tanto, la operación fundamental del modificador __block es cambiar la dirección de memoria de una variable externa, no simplemente hacer efectiva la operación de escritura.

2. Además, si la variable externa capturada por el bloque se modifica con estática o la variable externa se declara como variable global, entonces el bloque puede modificar directamente la variable externa, porque la dirección de la variable global o variable estática en la memoria es fija (almacenada En el área estática de arriba), cuando el Bloque lee el valor de la variable, lo lee directamente de la memoria donde se encuentra, y obtiene el último valor en lugar de la constante copiada en el momento de la definición.

 

Como se muestra en la figura anterior, los bloques que capturan variables estáticas y variables globales pueden modificar directamente sus valores, cabe señalar que aunque el bloque captura variables externas en este momento, sigue siendo un bloque ubicado en el área global.




Enlace de referencia: https://www.jianshu.com/p/9c67b7716723

Supongo que te gusta

Origin blog.csdn.net/wangletiancsdn/article/details/99677530
Recomendado
Clasificación