Gestión de la memoria
*********************


Visión general
==============

La gestión de memoria en Python implica un montón privado que contiene
todos los objetos de Python y estructuras de datos. El *administrador
de memoria de Python* garantiza internamente la gestión de este montón
privado. El administrador de memoria de Python tiene diferentes
componentes que se ocupan de varios aspectos de la gestión dinámica
del almacenamiento, como compartir, segmentación, asignación previa o
almacenamiento en caché.

En el nivel más bajo, un asignador de memoria sin procesar asegura que
haya suficiente espacio en el montón privado para almacenar todos los
datos relacionados con Python al interactuar con el administrador de
memoria del sistema operativo. Además del asignador de memoria sin
procesar, varios asignadores específicos de objeto operan en el mismo
montón e implementan políticas de administración de memoria distintas
adaptadas a las peculiaridades de cada tipo de objeto. Por ejemplo,
los objetos enteros se administran de manera diferente dentro del
montón que las cadenas, tuplas o diccionarios porque los enteros
implican diferentes requisitos de almacenamiento y compensaciones de
velocidad / espacio. El administrador de memoria de Python delega
parte del trabajo a los asignadores específicos de objeto, pero
asegura que este último opere dentro de los límites del montón
privado.

Es importante comprender que la gestión del montón de Python la
realiza el propio intérprete y que el usuario no tiene control sobre
él, incluso si manipulan regularmente punteros de objetos a bloques de
memoria dentro de ese montón. El administrador de memoria de Python
realiza la asignación de espacio de almacenamiento dinámico para los
objetos de Python y otros búferes internos a pedido a través de las
funciones de API de Python/C enumeradas en este documento.

Para evitar daños en la memoria, los escritores de extensiones nunca
deberían intentar operar en objetos Python con las funciones
exportadas por la biblioteca C: "malloc()", "calloc()", "realloc()" y
"free()". Esto dará como resultado llamadas mixtas entre el asignador
de C y el administrador de memoria de Python con consecuencias
fatales, ya que implementan diferentes algoritmos y operan en
diferentes montones. Sin embargo, uno puede asignar y liberar de forma
segura bloques de memoria con el asignador de la biblioteca C para
fines individuales, como se muestra en el siguiente ejemplo:

   PyObject *res;
   char *buf = (char *) malloc(BUFSIZ); /* for I/O */

   if (buf == NULL)
       return PyErr_NoMemory();
   ...Do some I/O operation involving buf...
   res = PyBytes_FromString(buf);
   free(buf); /* malloc'ed */
   return res;

En este ejemplo, la solicitud de memoria para el búfer de E/S es
manejada por el asignador de la biblioteca C. El administrador de
memoria de Python solo participa en la asignación del objeto de bytes
retornado como resultado.

Sin embargo, en la mayoría de las situaciones, se recomienda asignar
memoria del montón de Python específicamente porque este último está
bajo el control del administrador de memoria de Python. Por ejemplo,
esto es necesario cuando el intérprete se amplía con nuevos tipos de
objetos escritos en C. Otra razón para usar el montón de Python es el
deseo de *informar* al administrador de memoria de Python sobre las
necesidades de memoria del módulo de extensión. Incluso cuando la
memoria solicitada se usa exclusivamente para fines internos y
altamente específicos, delegar todas las solicitudes de memoria al
administrador de memoria de Python hace que el intérprete tenga una
imagen más precisa de su huella de memoria en su conjunto. En
consecuencia, bajo ciertas circunstancias, el administrador de memoria
de Python puede o no desencadenar acciones apropiadas, como
recolección de basura, compactación de memoria u otros procedimientos
preventivos. Tenga en cuenta que al usar el asignador de la biblioteca
C como se muestra en el ejemplo anterior, la memoria asignada para el
búfer de E/S escapa completamente al administrador de memoria Python.

Ver también:

  La variable de entorno "PYTHONMALLOC" puede usarse para configurar
  los asignadores de memoria utilizados por Python.

  La variable de entorno "PYTHONMALLOCSTATS" se puede utilizar para
  imprimir estadísticas de asignador de memoria pymalloc cada vez que
  se crea un nuevo escenario de objetos pymalloc, y en el apagado.


Dominios del asignador
======================

Todas las funciones de asignación pertenecen a uno de los tres
"dominios" diferentes (ver también "PyMemAllocatorDomain"). Estos
dominios representan diferentes estrategias de asignación y están
optimizados para diferentes propósitos. Los detalles específicos sobre
cómo cada dominio asigna memoria o qué funciones internas llama cada
dominio se considera un detalle de implementación, pero para fines de
depuración, se puede encontrar una tabla simplificada en here. No
existe un requisito estricto para usar la memoria retornada por las
funciones de asignación que pertenecen a un dominio dado solo para los
propósitos sugeridos por ese dominio (aunque esta es la práctica
recomendada). Por ejemplo, se podría usar la memoria retornada por
"PyMem_RawMalloc()" para asignar objetos Python o la memoria retornada
por "PyObject_Malloc()" para asignar memoria para búferes.

Los tres dominios de asignación son:

* Dominio sin formato: destinado a asignar memoria para búferes de
  memoria de uso general donde la asignación *debe* ir al asignador
  del sistema o donde el asignador puede operar sin el *GIL*. La
  memoria se solicita directamente al sistema.

* Dominio "Mem": destinado a asignar memoria para búferes de Python y
  búferes de memoria de propósito general donde la asignación debe
  realizarse con el *GIL* retenido. La memoria se toma del montículo
  privado de Python.

* Dominio de objeto: destinado a asignar memoria perteneciente a
  objetos de Python. La memoria se toma del montículo privado de
  Python.

Cuando se libera memoria previamente asignada por las funciones de
asignación que pertenecen a un dominio dado, se deben utilizar las
funciones de desasignación específicas coincidentes. Por ejemplo,
"PyMem_Free()" debe usarse para liberar memoria asignada usando
"PyMem_Malloc()".


Interfaz de memoria sin procesar
================================

Los siguientes conjuntos de funciones son envoltorios para el
asignador del sistema. Estas funciones son seguras para subprocesos,
no es necesario mantener el *GIL*.

The default raw memory allocator uses the following functions:
"malloc()", "calloc()", "realloc()" and "free()"; call "malloc(1)" (or
"calloc(1, 1)") when requesting zero bytes.

Added in version 3.4.

void *PyMem_RawMalloc(size_t n)

   Asigna *n* bytes y retorna un puntero de tipo void* a la memoria
   asignada, o "NULL" si la solicitud falla.

   Solicitar cero bytes retorna un puntero distinto que no sea "NULL"
   si es posible, como si en su lugar se hubiera llamado a
   "PyMem_RawMalloc(1)". La memoria no se habrá inicializado de
   ninguna manera.

void *PyMem_RawCalloc(size_t nelem, size_t elsize)

   Asigna *nelem* elementos cada uno cuyo tamaño en bytes es *elsize*
   y retorna un puntero de tipo void* a la memoria asignada, o "NULL"
   si la solicitud falla. La memoria se inicializa a ceros.

   Solicitar elementos cero o elementos de tamaño cero bytes retorna
   un puntero distinto "NULL" si es posible, como si en su lugar se
   hubiera llamado "PyMem_RawCalloc(1, 1)".

   Added in version 3.5.

void *PyMem_RawRealloc(void *p, size_t n)

   Cambia el tamaño del bloque de memoria señalado por *p* a *n*
   bytes. Los contenidos no se modificarán al mínimo de los tamaños
   antiguo y nuevo.

   Si *p* es "NULL", la llamada es equivalente a "PyMem_RawMalloc(n)";
   de lo contrario, si *n* es igual a cero, el bloque de memoria
   cambia de tamaño pero no se libera, y el puntero retornado no es
   "NULL".

   A menos que *p* sea "NULL", debe haber sido retornado por una
   llamada previa a "PyMem_RawMalloc()", "PyMem_RawRealloc()" o
   "PyMem_RawCalloc()".

   Si la solicitud falla, "PyMem_RawRealloc()" retorna "NULL" y *p*
   sigue siendo un puntero válido al área de memoria anterior.

void PyMem_RawFree(void *p)

   Libera el bloque de memoria al que apunta *p*, que debe haber sido
   retornado por una llamada anterior a "PyMem_RawMalloc()",
   "PyMem_RawRealloc()" o "PyMem_RawCalloc()". De lo contrario, o si
   se ha llamado antes a "PyMem_RawFree(p)", se produce un
   comportamiento indefinido.

   Si *p* es "NULL", no se realiza ninguna operación.


Interfaz de memoria
===================

Los siguientes conjuntos de funciones, modelados según el estándar
ANSI C, pero que especifican el comportamiento cuando se solicitan
cero bytes, están disponibles para asignar y liberar memoria del
montón de Python.

El asignador de memoria predeterminado usa el asignador de memorya
pymalloc.

Advertencia:

  El *GIL* debe mantenerse cuando se utilizan estas funciones.

Distinto en la versión 3.6: El asignador predeterminado ahora es
pymalloc en lugar del "malloc()" del sistema.

void *PyMem_Malloc(size_t n)
    * Part of the Stable ABI.*

   Asigna *n* bytes y retorna un puntero de tipo void* a la memoria
   asignada, o "NULL" si la solicitud falla.

   Solicitar cero bytes retorna un puntero distinto que no sea "NULL"
   si es posible, como si en su lugar se hubiera llamado a
   "PyMem_Malloc(1)". La memoria no se habrá inicializado de ninguna
   manera.

void *PyMem_Calloc(size_t nelem, size_t elsize)
    * Part of the Stable ABI since version 3.7.*

   Asigna *nelem* elementos cada uno cuyo tamaño en bytes es *elsize*
   y retorna un puntero de tipo void* a la memoria asignada, o "NULL"
   si la solicitud falla. La memoria se inicializa a ceros.

   Solicitar elementos cero o elementos de tamaño cero bytes retorna
   un puntero distinto "NULL" si es posible, como si en su lugar se
   hubiera llamado "PyMem_Calloc(1, 1)".

   Added in version 3.5.

void *PyMem_Realloc(void *p, size_t n)
    * Part of the Stable ABI.*

   Cambia el tamaño del bloque de memoria señalado por *p* a *n*
   bytes. Los contenidos no se modificarán al mínimo de los tamaños
   antiguo y nuevo.

   Si *p* es "NULL", la llamada es equivalente a "PyMem_Malloc(n)"; de
   lo contrario, si *n* es igual a cero, el bloque de memoria cambia
   de tamaño pero no se libera, y el puntero retornado no es "NULL".

   A menos que *p* sea "NULL", debe haber sido retornado por una
   llamada previa a "PyMem_Malloc()", "PyMem_Realloc()" o
   "PyMem_Calloc()".

   Si la solicitud falla, "PyMem_Realloc()" retorna "NULL" y *p* sigue
   siendo un puntero válido al área de memoria anterior.

void PyMem_Free(void *p)
    * Part of the Stable ABI.*

   Libera el bloque de memoria señalado por *p*, que debe haber sido
   retornado por una llamada anterior a "PyMem_Malloc()",
   "PyMem_Realloc()" o "PyMem_Calloc()". De lo contrario, o si se ha
   llamado antes a "PyMem_Free(p)", se produce un comportamiento
   indefinido.

   Si *p* es "NULL", no se realiza ninguna operación.

Las siguientes macros orientadas a tipos se proporcionan por
conveniencia. Tenga en cuenta que *TYPE* se refiere a cualquier tipo
de C.

PyMem_New(TYPE, n)

   Same as "PyMem_Malloc()", but allocates "(n * sizeof(TYPE))" bytes
   of memory.  Returns a pointer cast to "TYPE*".  The memory will not
   have been initialized in any way.

PyMem_Resize(p, TYPE, n)

   Same as "PyMem_Realloc()", but the memory block is resized to "(n *
   sizeof(TYPE))" bytes.  Returns a pointer cast to "TYPE*". On
   return, *p* will be a pointer to the new memory area, or "NULL" in
   the event of failure.

   Esta es una macro de preprocesador C; *p* siempre se reasigna.
   Guarde el valor original de *p* para evitar perder memoria al
   manejar errores.

void PyMem_Del(void *p)

   La misma que "PyMem_Free()".

Además, se proporcionan los siguientes conjuntos de macros para llamar
al asignador de memoria de Python directamente, sin involucrar las
funciones de API de C mencionadas anteriormente. Sin embargo, tenga en
cuenta que su uso no conserva la compatibilidad binaria entre las
versiones de Python y, por lo tanto, está en desuso en los módulos de
extensión.

* "PyMem_MALLOC(size)"

* "PyMem_NEW(type, size)"

* "PyMem_REALLOC(ptr, size)"

* "PyMem_RESIZE(ptr, type, size)"

* "PyMem_FREE(ptr)"

* "PyMem_DEL(ptr)"


Asignadores de objetos
======================

Los siguientes conjuntos de funciones, modelados según el estándar
ANSI C, pero que especifican el comportamiento cuando se solicitan
cero bytes, están disponibles para asignar y liberar memoria del
montón de Python.

Nota:

  No hay garantía de que la memoria retornada por estos asignadores se
  pueda convertir con éxito en un objeto Python al interceptar las
  funciones de asignación en este dominio mediante los métodos
  descritos en la sección Personalizar Asignadores de Memoria.

El asignador predeterminado de objetos usa el asignador de memoria
pymalloc.

Advertencia:

  El *GIL* debe mantenerse cuando se utilizan estas funciones.

void *PyObject_Malloc(size_t n)
    * Part of the Stable ABI.*

   Asigna *n* bytes y retorna un puntero de tipo void* a la memoria
   asignada, o "NULL" si la solicitud falla.

   Solicitar cero bytes retorna un puntero distinto que no sea "NULL"
   si es posible, como si en su lugar se hubiera llamado a
   "PyObject_Malloc(1)". La memoria no se habrá inicializado de
   ninguna manera.

void *PyObject_Calloc(size_t nelem, size_t elsize)
    * Part of the Stable ABI since version 3.7.*

   Asigna *nelem* elementos cada uno cuyo tamaño en bytes es *elsize*
   y retorna un puntero de tipo void* a la memoria asignada, o "NULL"
   si la solicitud falla. La memoria se inicializa a ceros.

   Solicitar elementos cero o elementos de tamaño cero bytes retorna
   un puntero distinto "NULL" si es posible, como si en su lugar se
   hubiera llamado "PyObject_Calloc(1, 1)".

   Added in version 3.5.

void *PyObject_Realloc(void *p, size_t n)
    * Part of the Stable ABI.*

   Cambia el tamaño del bloque de memoria señalado por *p* a *n*
   bytes. Los contenidos no se modificarán al mínimo de los tamaños
   antiguo y nuevo.

   Si *p* es "NULL", la llamada es equivalente a "PyObject_Malloc(n)";
   de lo contrario, si *n* es igual a cero, el bloque de memoria
   cambia de tamaño pero no se libera, y el puntero retornado no es
   "NULL".

   A menos que *p* sea "NULL", debe haber sido retornado por una
   llamada previa a "PyObject_Malloc()", "PyObject_Realloc()" o
   "PyObject_Calloc()".

   Si la solicitud falla, "PyObject_Realloc()" retorna "NULL" y *p*
   sigue siendo un puntero válido al área de memoria anterior.

void PyObject_Free(void *p)
    * Part of the Stable ABI.*

   Libera el bloque de memoria al que apunta *p*, que debe haber sido
   retornado por una llamada anterior a "PyObject_Malloc()",
   "PyObject_Realloc()" o "PyObject_Calloc()". De lo contrario, o si
   se ha llamado antes a "PyObject_Free(p)", se produce un
   comportamiento indefinido.

   Si *p* es "NULL", no se realiza ninguna operación.


Asignadores de memoria predeterminados
======================================

Asignadores de memoria predeterminados:

+---------------------------------+----------------------+--------------------+-----------------------+----------------------+
| Configuración                   | Nombre               | PyMem_RawMalloc    | PyMem_Malloc          | PyObject_Malloc      |
|=================================|======================|====================|=======================|======================|
| Lanzamiento de compilación      | ""pymalloc""         | "malloc"           | "malloc" + debug      | "malloc" + debug     |
+---------------------------------+----------------------+--------------------+-----------------------+----------------------+
| Compilación de depuración       | ""pymalloc_debug""   | "malloc" + debug   | "pymalloc" + debug    | "pymalloc" + debug   |
+---------------------------------+----------------------+--------------------+-----------------------+----------------------+
| Lanzamiento de compilación, sin | ""malloc""           | "malloc"           | "malloc"              | "malloc"             |
| pymalloc                        |                      |                    |                       |                      |
+---------------------------------+----------------------+--------------------+-----------------------+----------------------+
| Compilación de depuración, sin  | ""malloc_debug""     | "malloc" + debug   | "malloc" + debug      | "malloc" + debug     |
| pymalloc                        |                      |                    |                       |                      |
+---------------------------------+----------------------+--------------------+-----------------------+----------------------+

Leyenda:

* Nombre: valor para variable de entorno "PYTHONMALLOC".

* "malloc": asignadores del sistema de la biblioteca C estándar,
  funciones C: "malloc()", "calloc()", "realloc()" y "free()".

* "pymalloc": asignador de memoria pymalloc.

* "+ debug": con enlaces de depuración en los asignadores de memoria
  de Python.

* "Debug build": Compilación de Python en modo de depuración.


Personalizar asignadores de memoria
===================================

Added in version 3.4.

type PyMemAllocatorEx

   Estructura utilizada para describir un asignador de bloque de
   memoria. La estructura tiene cuatro campos:

   +------------------------------------------------------------+-----------------------------------------+
   | Campo                                                      | Significado                             |
   |============================================================|=========================================|
   | "void *ctx"                                                | contexto de usuario pasado como primer  |
   |                                                            | argumento                               |
   +------------------------------------------------------------+-----------------------------------------+
   | "void* malloc(void *ctx, size_t size)"                     | asignar un bloque de memoria            |
   +------------------------------------------------------------+-----------------------------------------+
   | "void* calloc(void *ctx, size_t nelem, size_t elsize)"     | asignar un bloque de memoria            |
   |                                                            | inicializado con ceros                  |
   +------------------------------------------------------------+-----------------------------------------+
   | "void* realloc(void *ctx, void *ptr, size_t new_size)"     | asignar o cambiar el tamaño de un       |
   |                                                            | bloque de memoria                       |
   +------------------------------------------------------------+-----------------------------------------+
   | "void free(void *ctx, void *ptr)"                          | liberar un bloque de memoria            |
   +------------------------------------------------------------+-----------------------------------------+

   Distinto en la versión 3.5: The "PyMemAllocator" structure was
   renamed to "PyMemAllocatorEx" and a new "calloc" field was added.

type PyMemAllocatorDomain

   Enum se utiliza para identificar un dominio asignador. Dominios:

   PYMEM_DOMAIN_RAW

      Funciones:

      * "PyMem_RawMalloc()"

      * "PyMem_RawRealloc()"

      * "PyMem_RawCalloc()"

      * "PyMem_RawFree()"

   PYMEM_DOMAIN_MEM

      Funciones:

      * "PyMem_Malloc()",

      * "PyMem_Realloc()"

      * "PyMem_Calloc()"

      * "PyMem_Free()"

   PYMEM_DOMAIN_OBJ

      Funciones:

      * "PyObject_Malloc()"

      * "PyObject_Realloc()"

      * "PyObject_Calloc()"

      * "PyObject_Free()"

void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)

   Obtenga el asignador de bloque de memoria del dominio especificado.

void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)

   Establece el asignador de bloque de memoria del dominio
   especificado.

   El nuevo asignador debe retornar un puntero distinto "NULL" al
   solicitar cero bytes.

   For the "PYMEM_DOMAIN_RAW" domain, the allocator must be thread-
   safe: the *GIL* is not held when the allocator is called.

   For the remaining domains, the allocator must also be thread-safe:
   the allocator may be called in different interpreters that do not
   share a "GIL".

   Si el nuevo asignador no es un enlace (no llama al asignador
   anterior), se debe llamar a la función "PyMem_SetupDebugHooks()"
   para reinstalar los enlaces de depuración en la parte superior del
   nuevo asignador.

   Vea también "PyPreConfig.allocator" y Preinicialización de Python
   con PyPreConfig.

   Advertencia:

     "PyMem_SetAllocator()" does have the following contract:

     * It can be called after "Py_PreInitialize()" and before
       "Py_InitializeFromConfig()" to install a custom memory
       allocator. There are no restrictions over the installed
       allocator other than the ones imposed by the domain (for
       instance, the Raw Domain allows the allocator to be called
       without the GIL held). See the section on allocator domains for
       more information.

     * If called after Python has finish initializing (after
       "Py_InitializeFromConfig()" has been called) the allocator
       **must** wrap the existing allocator. Substituting the current
       allocator for some other arbitrary one is **not supported**.

   Distinto en la versión 3.12: All allocators must be thread-safe.

void PyMem_SetupDebugHooks(void)

   Configurar enlaces de depuración en los asignadores de memoria de
   Python para detectar errores de memoria.


Configurar enlaces para detectar errores en las funciones del asignador de memoria de Python
============================================================================================

Cuando Python está construido en modo de depuración, la función
"PyMem_SetupDebugHooks()" se llama en Preinicialización de Python para
configurar los enlaces de depuración en Python asignadores de memoria
para detectar errores de memoria.

La variable de entorno "PYTHONMALLOC" se puede utilizar para instalar
enlaces de depuración en un Python compilado en modo de lanzamiento
(por ejemplo: "PYTHONMALLOC=debug").

La función "PyMem_SetupDebugHooks()" se puede utilizar para establecer
enlaces de depuración después de llamar a "PyMem_SetAllocator()".

Estos enlaces de depuración llenan bloques de memoria asignados
dinámicamente con patrones de bits especiales y reconocibles. La
memoria recién asignada se llena con el byte "0xCD"
("PYMEM_CLEANBYTE"), la memoria liberada se llena con el byte "0xDD"
("PYMEM_DEADBYTE"). Los bloques de memoria están rodeados por "bytes
prohibidos" rellenos con el byte "0xFD" ("PYMEM_FORBIDDENBYTE"). Es
poco probable que las cadenas de estos bytes sean direcciones válidas,
flotantes o cadenas ASCII.

Verificaciones de tiempo de ejecución:

* Detecte violaciones de API, por ejemplo: "PyObject_Free()" llamado
  en un búfer asignado por "PyMem_Malloc()".

* Detectar escritura antes del inicio del búfer (desbordamiento del
  búfer)

* Detectar escritura después del final del búfer (desbordamiento del
  búfer)

* Check that the *GIL* is held when allocator functions of
  "PYMEM_DOMAIN_OBJ" (ex: "PyObject_Malloc()") and "PYMEM_DOMAIN_MEM"
  (ex: "PyMem_Malloc()") domains are called.

En caso de error, los enlaces de depuración usan el módulo
"tracemalloc" para obtener el rastreo donde se asignó un bloque de
memoria. El rastreo solo se muestra si "tracemalloc" rastrea las
asignaciones de memoria de Python y se rastrea el bloque de memoria.

Sea *S* = "sizeof(size_t)". Se agregan "2*S" bytes en cada extremo de
cada bloque de *N* bytes solicitados. El diseño de la memoria es así,
donde p representa la dirección retornada por una función similar a
malloc o realloc ("p[i:j]" significa el segmento de bytes de "*(p+i)"
inclusive hasta "*(p+j)" exclusivo; tenga en cuenta que el tratamiento
de los índices negativos difiere de un segmento de Python):

"p[-2*S:-S]"
   Número de bytes solicitados originalmente. Este es un size_t, big-
   endian (más fácil de leer en un volcado de memoria).

"p[-S]"
   Identificador de API (carácter ASCII):

   * "'r'" for "PYMEM_DOMAIN_RAW".

   * "'m'" for "PYMEM_DOMAIN_MEM".

   * "'o'" for "PYMEM_DOMAIN_OBJ".

"p[-S+1:0]"
   Copias de PYMEM_FORBIDDENBYTE. Se utiliza para detectar
   suscripciones y lecturas.

"p[0:N]"
   La memoria solicitada, llena de copias de PYMEM_CLEANBYTE,
   utilizada para capturar la referencia a la memoria no inicializada.
   Cuando se llama a una función similar a realloc solicitando un
   bloque de memoria más grande, los nuevos bytes en exceso también se
   llenan con PYMEM_CLEANBYTE. Cuando se llama a una función de tipo
   free, se sobrescriben con PYMEM_DEADBYTE, para captar la referencia
   a la memoria liberada. Cuando se llama a una función similar a la
   realloc solicitando un bloque de memoria más pequeño, los bytes
   antiguos sobrantes también se llenan con PYMEM_DEADBYTE.

"p[N:N+S]"
   Copias de PYMEM_FORBIDDENBYTE. Se utiliza para detectar
   sobrescrituras y lecturas.

"p[N+S:N+2*S]"
   Solo se utiliza si la macro "PYMEM_DEBUG_SERIALNO" está definida
   (no definida por defecto).

   A serial number, incremented by 1 on each call to a malloc-like or
   realloc-like function.  Big-endian "size_t".  If "bad memory" is
   detected later, the serial number gives an excellent way to set a
   breakpoint on the next run, to capture the instant at which this
   block was passed out.  The static function bumpserialno() in
   obmalloc.c is the only place the serial number is incremented, and
   exists so you can set such a breakpoint easily.

Una función de tipo realloc o de tipo free primero verifica que los
bytes PYMEM_FORBIDDENBYTE en cada extremo estén intactos. Si se han
modificado, la salida de diagnóstico se escribe en stderr y el
programa se aborta mediante Py_FatalError(). El otro modo de falla
principal es provocar un error de memoria cuando un programa lee uno
de los patrones de bits especiales e intenta usarlo como una
dirección. Si ingresa a un depurador y observa el objeto, es probable
que vea que está completamente lleno de PYMEM_DEADBYTE (lo que
significa que se está usando la memoria liberada) o PYMEM_CLEANBYTE
(que significa que se está usando la memoria no inicializada).

Distinto en la versión 3.6: The "PyMem_SetupDebugHooks()" function now
also works on Python compiled in release mode.  On error, the debug
hooks now use "tracemalloc" to get the traceback where a memory block
was allocated. The debug hooks now also check if the GIL is held when
functions of "PYMEM_DOMAIN_OBJ" and "PYMEM_DOMAIN_MEM" domains are
called.

Distinto en la versión 3.8: Los patrones de bytes "0xCB"
("PYMEM_CLEANBYTE"), "0xDB" ("PYMEM_DEADBYTE") y "0xFB"
("PYMEM_FORBIDDENBYTE") se han reemplazado por "0xCD", "0xDD" y "0xFD"
para usar los mismos valores que la depuración de Windows CRT
"malloc()" y "free()".


El asignador pymalloc
=====================

Python has a *pymalloc* allocator optimized for small objects (smaller
or equal to 512 bytes) with a short lifetime. It uses memory mappings
called "arenas" with a fixed size of either 256 KiB on 32-bit
platforms or 1 MiB on 64-bit platforms. It falls back to
"PyMem_RawMalloc()" and "PyMem_RawRealloc()" for allocations larger
than 512 bytes.

*pymalloc* is the default allocator of the "PYMEM_DOMAIN_MEM" (ex:
"PyMem_Malloc()") and "PYMEM_DOMAIN_OBJ" (ex: "PyObject_Malloc()")
domains.

El asignador de arena utiliza las siguientes funciones:

* "VirtualAlloc()" and "VirtualFree()" on Windows,

* "mmap()" and "munmap()" if available,

* "malloc()" y "free()" en caso contrario.

Este asignador está deshabilitado si Python está configurado con la
opción "--without-pymalloc". También se puede deshabilitar en tiempo
de ejecución usando la variable de entorno "PYTHONMALLOC" (por
ejemplo: "PYTHONMALLOC=malloc").


Personalizar asignador de arena de pymalloc
-------------------------------------------

Added in version 3.4.

type PyObjectArenaAllocator

   Estructura utilizada para describir un asignador de arena. La
   estructura tiene tres campos:

   +----------------------------------------------------+-----------------------------------------+
   | Campo                                              | Significado                             |
   |====================================================|=========================================|
   | "void *ctx"                                        | contexto de usuario pasado como primer  |
   |                                                    | argumento                               |
   +----------------------------------------------------+-----------------------------------------+
   | "void* alloc(void *ctx, size_t size)"              | asignar una arena de bytes de tamaño    |
   +----------------------------------------------------+-----------------------------------------+
   | "void free(void *ctx, void *ptr, size_t size)"     | liberar la arena                        |
   +----------------------------------------------------+-----------------------------------------+

void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)

   Consigue el asignador de arena.

void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)

   Establecer el asignador de arena.


tracemalloc C API
=================

Added in version 3.7.

int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)

   Rastree un bloque de memoria asignado en el módulo "tracemalloc".

   Retorna "0" en caso de éxito, retorna "-1" en caso de error (no se
   pudo asignar memoria para almacenar la traza). Retorna "-2" si
   tracemalloc está deshabilitado.

   Si el bloque de memoria ya está rastreado, actualice el rastreo
   existente.

int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)

   Descomprima un bloque de memoria asignado en el módulo
   "tracemalloc". No haga nada si el bloque no fue rastreado.

   Retorna "-2" si tracemalloc está deshabilitado; de lo contrario,
   retorna "0".


Ejemplos
========

Aquí está el ejemplo de la sección Visión general, reescrito para que
el búfer de E/S se asigne desde el montón de Python utilizando el
primer conjunto de funciones:

   PyObject *res;
   char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */

   if (buf == NULL)
       return PyErr_NoMemory();
   /* ...Do some I/O operation involving buf... */
   res = PyBytes_FromString(buf);
   PyMem_Free(buf); /* allocated with PyMem_Malloc */
   return res;

El mismo código que utiliza el conjunto de funciones orientado a
tipos:

   PyObject *res;
   char *buf = PyMem_New(char, BUFSIZ); /* for I/O */

   if (buf == NULL)
       return PyErr_NoMemory();
   /* ...Do some I/O operation involving buf... */
   res = PyBytes_FromString(buf);
   PyMem_Del(buf); /* allocated with PyMem_New */
   return res;

Tenga en cuenta que en los dos ejemplos anteriores, el búfer siempre
se manipula a través de funciones que pertenecen al mismo conjunto. De
hecho, es necesario usar la misma familia de API de memoria para un
bloque de memoria dado, de modo que el riesgo de mezclar diferentes
asignadores se reduzca al mínimo. La siguiente secuencia de código
contiene dos errores, uno de los cuales está etiquetado como *fatal*
porque mezcla dos asignadores diferentes que operan en montones
diferentes.:

   char *buf1 = PyMem_New(char, BUFSIZ);
   char *buf2 = (char *) malloc(BUFSIZ);
   char *buf3 = (char *) PyMem_Malloc(BUFSIZ);
   ...
   PyMem_Del(buf3);  /* Wrong -- should be PyMem_Free() */
   free(buf2);       /* Right -- allocated via malloc() */
   free(buf1);       /* Fatal -- should be PyMem_Del()  */

In addition to the functions aimed at handling raw memory blocks from
the Python heap, objects in Python are allocated and released with
"PyObject_New", "PyObject_NewVar" and "PyObject_Del()".

Esto se explicará en el próximo capítulo sobre cómo definir e
implementar nuevos tipos de objetos en C.
