Elmi
cuando uso malloc()
arena free()
Al azar, anidados y con diferentes tamaños, en algún momento la memoria se fragmentará porque estas operaciones dejan una gran lista de pequeñas áreas de memoria que no son contiguas y, por lo tanto, no se pueden asignar como una pieza más grande.
Algunas preguntas sobre esto:
-
Cuando esto se hace con bastante frecuencia, la memoria se ve obligada a fragmentarse y luego todas estas áreas de memoria son
free()
d, ¿puedo suponer que estas áreas libres están concatenadas a su tamaño contiguo original? -
Cuando siempre hago un
malloc()
seguido porfree()
para la misma memoria y nunca anidar estas llamadas, ¿la memoria también está fragmentada en este escenario cuando los tamaños asignados/liberados son siempre diferentes?
No, no hay garantía. Según N1570, 7.22.3 Funciones de gestión de memoria:
No se especifica el orden y la contigüidad del almacenamiento asignado por llamadas sucesivas a las funciones alineado_alloc, calloc, malloc y realloc.
De todos modos, tienes dos opciones para elegir:
- Confíe plenamente en las funciones de gestión de memoria de la biblioteca.
- Escribe tus propios administradores de memoria, si eres De Verdad seguro.
Si yo fuera usted, definitivamente confiaría en las funciones existentes, porque las implementaciones modernas son súper inteligentes.
-
En realidad, dado que la pregunta está (también) etiquetada como C++, las dos posibilidades no se excluyen mutuamente. Puedes anular
operator new
en una base de clase por clase.– MSalters
12 mayo 2016 a las 12:51
sjsam
según ISO/CEI 9899:201x -> 7.22.3
No se especifica el orden y la contigüidad del almacenamiento asignado por llamadas sucesivas a las funciones alineado_alloc, calloc, malloc y realloc.
Un buen administrador de memoria podrá abordar el problema hasta cierto punto. Sin embargo, hay otros aspectos como la alineación de datos [1] lo que provoca fragmentación interna.
¿Qué podría hacer si confía en la administración de memoria incorporada?
-
Use un generador de perfiles, digamos valgrind, con la opción de verificación de memoria para encontrar la memoria que no se libera después del uso. Ejemplo:
valgrind --leak-check=yes myprog arg1 arg2
-
Seguir buenas prácticas. Ejemplo: en C++, si pretende que otros hereden de su clase polimórfica, puede declarar su destructor virtual.
-
Utilice punteros inteligentes.
Notas:
-
Si tuviera que utilizar su propio sistema de gestión de memoria, puede considerar Boehm-Demers-Weiser recolector de basura.
-
Valgrind Marco de instrumentación.
- La memoria que no se libera después del uso contribuirá a la fragmentación.
Todo esto depende de la implementación. Pero, sí, un buen administrador de memoria concatenará porciones de memoria libres contiguas. Y, sí, si haces un
malloc
seguido de unfree
y no llamas a ninguna función de biblioteca que llamemalloc
en el medio, entonces no debería ocurrir fragmentación.– Jabberwocky
12 de mayo de 2016 a las 12:14
Puede ejecutar Valgrind con su programa valgrind.org y compruebe si hay errores de alineación de datos y fugas de memoria.
– Niklas Rosencrantz
12 mayo 2016 a las 12:20
Es bastante difícil fragmentar un espacio de direcciones de 64 bits. Claro, puede fragmentarlo fácilmente hasta el punto en que ya no puede asignar un objeto de 10 TB, pero probablemente no tenía 10 TB de RAM de todos modos.
– MSalters
12 mayo 2016 a las 12:56
1. no. 2. no. Si el asignador de memoria hace ASLR, podría evitar activamente ser tan predecible como desea que sea. La solución es usar una arquitectura con un gran espacio de direcciones e ignorar la fragmentación, con punteros de 64 bits y grandes tamaños de memoria de hoy. La fragmentación es principalmente un problema de ayer, a menos que tenga alguna aplicación muy específica.
– Arte
12 mayo 2016 a las 13:02
¿Cómo funcionaría eso de todos modos? C no proporciona una recolección de basura, menos compactación del espacio de memoria. Simplemente no puede, ya que no hay información sobre dónde existen los punteros a los objetos.
– demasiado honesto para este sitio
12 mayo 2016 a las 13:09