Tecnología · GUÍA PRÁCTICA
¿mmap no puede cerrar los punteros exportados? Siga cada referencia antes de cambiar el array
Liberar la vista principal o borrar un nombre no elimina necesariamente sus cortes ni alias. Demuestre si el resultado toma prestado el mapeo o posee una copia independiente.

BufferError en mmap.close() puede indicar que alguien todavía necesita la memoria prestada. Eliminar la excepción cambiando el constructor del array no demuestra por sí solo que la vida útil sea segura.
Empiece por un mapa de referencias: mapeo, vistas directas, vistas derivadas y todos los arrays retenidos. Ocho controles locales distinguen borrar un nombre, terminar un préstamo y crear datos independientes.
1. Identifique al propietario y las referencias que salen
Anote las versiones de Python y NumPy, el constructor del mapeo, el dtype y dónde sale cada resultado. np.frombuffer crea una vista de su entrada. Un corte básico puede crear otra vista; alias = arr añade otro nombre al mismo array. Ninguna operación garantiza un búfer independiente.
Decida el contrato de la API antes de reparar la limpieza. Un resultado prestado exige que el propietario permanezca activo hasta terminar todos los usos. Un resultado que deba sobrevivir al propietario necesita almacenamiento independiente. Solo lectura describe las escrituras permitidas mediante esa vista: no convierte la memoria prestada en una copia propia.
2. Qué mostraron los ocho controles locales
Usamos CPython 3.12.14 y NumPy 2.3.5 en Linux con mapeos anónimos nuevos de ocho bytes que contenían valores de 0 a 7. Un memoryview directo bloqueó el cierre hasta release(). Un corte siguió bloqueándolo después de liberar la vista principal; liberar el corte permitió cerrar. Una vista derivada de solo lectura se comportó igual.
np.frombuffer(mm,dtype=np.uint8) bloqueó el cierre mientras vivió su array. Mantener arr[:2] activo lo siguió bloqueando después de borrar arr. Mantener alias = arr también. Eliminar la referencia NumPy restante permitió cerrar en estos ejemplos simples de CPython. Esto no convierte del arr en una garantía general si existen cachés, contenedores, cierres léxicos o ciclos de referencias.
3. Copiar cambia el contrato de vida útil
En el séptimo caso, owned = arr.copy() creó un array uint8 independiente. Tras eliminar el array prestado, el mapeo se cerró y owned.tolist() todavía devolvió 0 a 7. En el octavo, owned = mm[:2] produjo bytes independientes que conservaron 0 y 1 después del cierre. Son copias con asignación adicional y sin sincronización continua con el mapeo.
Copie mientras el origen sea válido y solo la región que deba salir. Borrar un nombre local no invalida el alias de otro llamador. No libere manualmente la cadena interna base de NumPy, no oculte el fallo de cierre ni cambie el constructor solo para eludir una protección. Si necesita cero copias, prolongue la vida del propietario mediante un contrato explícito de la aplicación.
4. Verifique por separado el cierre y los datos conservados
Con memoryview, termine cada vista derivada retenida y su principal en un ámbito deliberado; los gestores de contexto solo cubren las vistas que gestionan. Con NumPy, termine todos los usos de cortes y alias prestados antes de cerrar al propietario. Si falla, examine las referencias en lugar de repetir close o suponer que la recolección de basura prueba que no queda ningún préstamo.
Los ocho casos comprobaron el cierre correcto después de su limpieza específica. Tras cerrar solo se leyeron copias independientes, nunca punteros prestados después del desmapeo. No probamos archivos reales, unlink de memoria compartida, usuarios concurrentes ni otros sistemas. En la aplicación compruebe por separado el cierre previsto y los valores copiados. La persistencia y el vaciado de archivos son otro contrato, no una solución para vistas exportadas pendientes.
