En la programación en C, puede pasar cualquier tipo de puntero que desee como argumento para liberar, ¿cómo sabe el tamaño de la memoria asignada para liberar? Cada vez que paso un puntero a alguna función, también tengo que pasar el tamaño (es decir, un conjunto de 10 elementos necesita recibir 10 como parámetro para conocer el tamaño del conjunto), pero no tengo que pasar el tamaño al Función libre. ¿Por qué no, y puedo usar esta misma técnica en mis propias funciones para evitar tener que cargar con la variable adicional de la longitud de la matriz?
385
Respuestas:
Cuando llama
malloc()
, especifica la cantidad de memoria para asignar. La cantidad de memoria realmente utilizada es un poco más que esto e incluye información adicional que registra (al menos) qué tan grande es el bloque. No puede (confiablemente) acceder a esa otra información, y tampoco debe :-).Cuando llama
free()
, simplemente mira la información adicional para averiguar qué tan grande es el bloque.fuente
malloc_size()
que acceder de forma confiable al tamaño de bloque desde unmalloc()
puntero ed. Pero no hay una forma confiable y portátil.free()
requiere que el programador informe con precisión qué tan grande era elmalloc()
bloque? Las pérdidas de memoria son lo suficientemente malas como están.malloc()
yfree()
, pero tiene que almacenar el tamaño de una matriz? ¿Por qué no harían posible hacer algo comoblockSize(ptr)
si estuvieran almacenando la información de todos modos?La mayoría de las implementaciones de las funciones de asignación de memoria C almacenarán información contable para cada bloque, ya sea en línea o por separado.
Una forma típica (en línea) es asignar realmente un encabezado y la memoria que solicitó, rellenados a un tamaño mínimo. Entonces, por ejemplo, si solicitó 20 bytes, el sistema puede asignar un bloque de 48 bytes:
La dirección que se le proporciona es la dirección del área de datos. Luego, cuando libere el bloque,
free
simplemente tomará la dirección que le dé y, suponiendo que no haya rellenado esa dirección o la memoria que la rodea, verifique la información contable inmediatamente antes. Gráficamente, eso estaría en la línea de:Tenga en cuenta que el tamaño del encabezado y el relleno están totalmente definidos por la implementación (en realidad, todo está definido por la implementación (a), pero la opción de contabilidad en línea es común).
Las sumas de verificación y los marcadores especiales que existen en la información contable son a menudo la causa de errores como "Arena de memoria corrupta" o "Doble libre" si los sobrescribe o los libera dos veces.
El relleno (para hacer que la asignación sea más eficiente) es la razón por la que a veces puedes escribir un poco más allá del final del espacio solicitado sin causar problemas (aún así, no hagas eso, es un comportamiento indefinido y, solo porque a veces funciona, no funciona) t significa que está bien hacerlo).
(una) He escrito implementaciones de
malloc
en sistemas embebidos donde obtuviste 128 bytes sin importar lo que pediste (ese era el tamaño de la estructura más grande del sistema), suponiendo que pediste 128 bytes o menos (las solicitudes de más cumplir con un valor de retorno NULL). Se usó una máscara de bits muy simple (es decir, no en línea) para decidir si se asignó un fragmento de 128 bytes o no.Otros que he desarrollado tenían diferentes grupos para fragmentos de 16 bytes, fragmentos de 64 bytes, fragmentos de 256 bytes y fragmentos de 1K, nuevamente usando una máscara de bits para decidir qué bloques se usaron o estaban disponibles.
Ambas opciones lograron reducir la sobrecarga de la información contable y aumentar la velocidad
malloc
yfree
(sin necesidad de fusionar bloques adyacentes al liberar), particularmente importante en el entorno en el que estábamos trabajando.fuente
malloc
es que le proporcione, para el caso exitoso, un bloque de memoria al menos tan grande como lo que solicitó. Los bloques individuales son contiguos en términos de cómo se accede a los elementos dentro de ellos, pero no es necesario que las arenas de las que provienen los bloques sean contiguas.void *x = malloc(200); free(x, 500);
se no va a terminar bien :-) En cualquier caso, la eficiencia, el real tamaño de la memoria intermedia puede ser más grande (que no se puede confiar en esta).De la
comp.lang.c
lista de preguntas frecuentes: ¿Cómo sabe free cuántos bytes liberar?La implementación malloc / free recuerda el tamaño de cada bloque a medida que se asigna, por lo que no es necesario recordarle el tamaño al liberarlo. (Por lo general, el tamaño se almacena adyacente al bloque asignado, por lo que las cosas generalmente se rompen mal si los límites del bloque asignado están incluso ligeramente sobrepasados)
fuente
free
. Tal vez la respuesta no te satisfaga, pero no creo que obtengas una con información más genéricamente aplicable :-)Esta respuesta se reubica desde ¿Cómo free () sabe cuánta memoria desasignar? donde se me impidió responder con una aparente pregunta duplicada. Esta respuesta debería ser relevante para este duplicado:
Para el caso de
malloc
, el asignador de almacenamiento dinámico almacena una asignación del puntero devuelto original a los detalles relevantes necesarios parafree
almacenar la memoria más adelante. Esto generalmente implica almacenar el tamaño de la región de memoria en cualquier forma relevante para el asignador en uso, por ejemplo, el tamaño bruto, o un nodo en un árbol binario utilizado para rastrear asignaciones, o un recuento de "unidades" de memoria en uso.free
no fallará si "renombra" el puntero, o lo duplica de alguna manera. Sin embargo, no se cuenta como referencia, y solo el primerofree
será correcto. Losfree
s adicionales son errores de "doble libre".Intentar
free
cualquier puntero con un valor diferente a los devueltos pormalloc
s anteriores , y aún no liberado, es un error. No es posible liberar parcialmente las regiones de memoria devueltas demalloc
.fuente
En una nota relacionada, la biblioteca GLib tiene funciones de asignación de memoria que no guardan el tamaño implícito, y luego simplemente pasa el parámetro de tamaño a libre. Esto puede eliminar parte de los gastos generales.
fuente
malloc()
yfree()
dependen del sistema / compilador, por lo que es difícil dar una respuesta específica.Más información sobre esta otra pregunta .
fuente
El administrador de almacenamiento dinámico almacenó la cantidad de memoria que pertenece al bloque asignado en algún lugar cuando llamó
malloc
.Nunca implementé uno yo mismo, pero supongo que la memoria justo en frente del bloque asignado podría contener la metainformación.
fuente
La técnica original era asignar un bloque un poco más grande y almacenar el tamaño al principio, luego dar a la aplicación el resto del blog. El espacio extra tiene un tamaño y posiblemente se vincula para enhebrar los bloques libres juntos para su reutilización.
Sin embargo, hay ciertos problemas con esos trucos, como el comportamiento deficiente de la memoria caché y la administración de la memoria. El uso de la memoria en el bloque tiende a ubicar cosas innecesariamente y también crea páginas sucias que complican el intercambio y la copia en escritura.
Entonces, una técnica más avanzada es mantener un directorio separado. También se han desarrollado enfoques exóticos donde las áreas de memoria usan los mismos tamaños de potencia de dos.
En general, la respuesta es: se asigna una estructura de datos separada para mantener el estado.
fuente
Para responder a la segunda mitad de su pregunta: sí, puede, y un patrón bastante común en C es el siguiente:
fuente
Cuando llamamos a malloc, simplemente consume más byte de su requisito. Este consumo de más bytes contiene información como suma de cheques, tamaño y otra información adicional. Cuando llamamos gratis en ese momento, va directamente a esa información adicional donde se encuentra la dirección y también cuánto bloque será gratis.
fuente
para responder a la segunda pregunta, sí, podría (más o menos) usar la misma técnica que
malloc()
simplemente asignando la primera celda dentro de cada matriz al tamaño de la matriz. que le permite enviar la matriz sin enviar un argumento de tamaño adicional.fuente