La fragmentación de la memoria es el mismo concepto que la fragmentación del disco: se refiere a un desperdicio de espacio porque las áreas en uso no se empaquetan lo suficientemente juntas.
Supongamos por un simple ejemplo de juguete que tiene diez bytes de memoria:
| | | | | | | | | | |
0 1 2 3 4 5 6 7 8 9
Ahora vamos a asignar tres bloques de tres bytes, el nombre de A, B, y C:
| A | A | A | B | B | B | C | C | C | |
0 1 2 3 4 5 6 7 8 9
Ahora deallocate bloque B:
| A | A | A | | | | C | C | C | |
0 1 2 3 4 5 6 7 8 9
Ahora lo que sucede si tratamos de asignar un bloque de cuatro bytes D? Bueno, tenemos cuatro bytes de memoria libre, pero no tenemos cuatro contiguos bytes de memoria libre, por lo que no podemos asignar D! Este es un uso ineficiente de la memoria, porque deberíamos haber podido almacenar D, pero no pudimos. Y no podemos mover C para dejar espacio, porque muy probablemente algunas variables en nuestro programa apuntan a C, y no podemos encontrar y cambiar automáticamente todos estos valores.
¿Cómo sabes que es un problema? Bueno, la señal más importante es que el tamaño de la memoria virtual de su programa es considerablemente mayor que la cantidad de memoria que está usando realmente. En un ejemplo del mundo real, tendría muchos más de diez bytes de memoria, por lo que D se asignaría comenzando con un byte 9 y los bytes 3-5 permanecerían sin usar a menos que luego asignara algo de tres bytes de longitud o menos.
En este ejemplo, 3 bytes no son demasiado para desperdiciar, pero consideren un caso más patológico donde dos asignaciones de un par de bytes son, por ejemplo, diez megabytes separados en memoria, y necesita asignar un bloque de tamaño 10 megabytes + 1 byte. Tienes que pedirle al sistema operativo más de diez megabytes más de memoria virtual para hacer eso, aunque estés a un paso de tener suficiente espacio.
¿Cómo lo previenen? Los peores casos tienden a surgir cuando crea y destruye objetos pequeños con frecuencia, ya que esto tiende a producir un efecto de "queso suizo" con muchos objetos pequeños separados por muchos agujeros pequeños, por lo que es imposible asignar objetos más grandes en esos agujeros. Cuando sepa que va a hacer esto, una estrategia efectiva es preasignar un gran bloque de memoria como grupo para sus objetos pequeños, y luego administrar manualmente la creación de los objetos pequeños dentro de ese bloque, en lugar de dejarlo el asignador predeterminado lo maneja.
En general, cuantas menos asignaciones hagas, menos memoria habrá de fragmentarse. Sin embargo, STL trata esto de manera bastante efectiva. Si tiene una cadena que está utilizando la totalidad de su asignación actual y le agrega un carácter, no se vuelve a asignar a su longitud actual más uno, dobla su longitud. Esta es una variación de la estrategia del "grupo para pequeñas asignaciones frecuentes". La cuerda está agarrando un gran trozo de memoria para que pueda manejar eficientemente pequeños aumentos de tamaño repetidos sin realizar reasignaciones repetidas y pequeñas. De hecho, todos los contenedores STL hacen este tipo de cosas, por lo que, en general, no tendrá que preocuparse demasiado por la fragmentación causada por la reasignación automática de contenedores STL.
Aunque, por supuesto, contenedores STL no reunir la memoria entre sí, por lo que si usted va a crear muchos pequeños contenedores (en lugar de unos contenedores que consiguen cambiar de tamaño con frecuencia) puede que tenga que preocuparse por la prevención fragmentación de la misma manera que lo haría con cualquier objeto pequeño creado con frecuencia, STL o no.
Muchos de los grandes respuestas, gracias a todos! – AshleysBrain
Ya hay muchas respuestas excelentes, pero aquí hay algunas imágenes de una aplicación real (Firefox) donde la fragmentación de la memoria era un gran problema: http://blog.pavlov.net/2007/11/10/memory-fragmentation/ –
@ MariusGedminas el enlace ya no funciona por eso es importante proporcionar un breve resumen junto con el enlace o responder la pregunta con un resumen con el enlace – katta