2010-10-17 26 views
10

Duplicar posible:
How do free and malloc work in C?¿Cómo funciona malloc?

Considere un escenario en el que tengo que destinar unos 20 bytes de memoria a través de malloc. Para la función, llame a malloc() para que tenga éxito, ¿deberían estar los 20 bytes contiguos en la memoria o pueden estar dispersos? Por ejemplo, en el caso anterior, si hay 4 o 5 fragmentos de 10 bytes cada uno, ¿malloc funcionará? ¿O es este sistema operativo específico o específico del compilador?

Respuesta

35

La pregunta es un poco errada.

En un sistema operativo típico, existen los conceptos de memoria virtual y memoria física.

La memoria física existe generalmente en bloques de 4 kb, memoria virtual de la misma manera.

Cada proceso tiene memoria virtual: para cada proceso, el sistema operativo presenta lo que parece ser el rango de memoria totalmente direccionable. Entonces en una máquina de 32 bits, cada proceso 'piensa' que tiene 4 GB de memoria contigua.

En realidad, el sistema operativo, detrás de las escenas, está ocupado asignando asignaciones de memoria virtual en bloques reales de memoria física. Por lo tanto, una asignación de memoria virtual de 400 kb, por ejemplo, se mapea en 100 bloques físicos. Esos bloques físicos no necesitan ser contigiosos (y casi nunca lo son, nada impide que ocurra, pero en una máquina que realiza cualquier tipo de trabajo, es altamente improbable), pero la asignación de memoria virtual tiene necesita ser contigiosa.

De modo que aún puede encontrarse con la fragmentación de memoria virtual. Aquí, un proceso solicita un bloque de memoria y no hay, en ese proceso particular, un mapa de memoria virtual, un bloque de memoria virtual contigua de modo que se pueda satisfacer la solicitud.

Ese problema es el problema que estás pensando.

+0

+1 muy informativo. – birryree

+0

arco humilde :-) [relleno adicional para la longitud de la publicación mínima] –

+1

Sin embargo, esto nunca afectará a un puntero devuelto de 'malloc'. – dawg

6

La norma malloc se define en el estándar C para asignar un bloque contiguo de memoria (al menos eso le parece a usted) - devolverá un puntero nulo si falla la asignación.

En un nivel inferior, el sistema operativo hará algo como lo que kotlinski o Blank Xavier han descrito en sus respectivas respuestas.

De §7.20.3 de la ISO/IEC 9899-1999 C Standard:

El puntero devuelto si la asignación (por calloc, realloc, o malloc) tiene éxito está alineado adecuadamente de modo que puede asignarse a un puntero a cualquier tipo de objeto y luego a utilizado para acceder a dicho objeto o a una matriz de dichos objetos en el espacio asignado (hasta que el espacio se desasigna explícitamente).

No es que explícita, pero el párrafo menciona 'para acceder a una gran variedad de tales objetos', y en la norma C, las matrices son:

un tipo de matriz describe un conjunto no vacío de forma contigua asignado de objetos con un tipo de objeto miembro particular, llamado tipo de elemento. (De §6.2.5)

También tenga en cuenta que las llamadas posteriores a calloc, realloc y malloc no garantizan la contigüidad o de ordenamiento de memoria (con otros bloques de memoria ya asignados).

Este punto también se especifica en §7.20.3.

El orden y la contigüidad de almacenamiento asignado por llamadas sucesivas a la calloc, malloc y realloc funciones no está especificado.

+0

La llamada posterior a 'realloc' VOLVERÁ un puntero a la memoria contigua de ese tamaño de error. También protegerá sus datos existentes en esa área si se asignaron correctamente antes. El puntero puede cambiar, y la dirección absoluta de sus datos puede cambiar, pero si 'realloc' tiene éxito, usted tiene sus datos originales y el bloque redimensionado como un bloque. Su última afirmación es falsa con respecto a 'realloc' ... – dawg

+1

Mi última afirmación puede no haber sido clara: quise decir que las llamadas repetidas a cualquiera de las funciones de asignación no garantizan la contigüidad/orden respectiva a otros bloques de memoria que ya tienen ha sido asignado, no que la memoria asignada por ellos no sea contigua. – birryree

2

La memoria tiene que ser continua - lo que usted está mencionando que se conoce generalmente como memory fragmentation, y es un problema real para aplicaciones de adquisición y liberación de memoria muy a menudo.

4

Esto es específico de la plataforma. A sus ojos, en el nivel de software, siempre se presentará como malloc: ed 20 bytes contiguos. Pero en algunas plataformas, p. con la memoria paginada, estos bytes realmente no necesitan ser contiguos cuando se trata del hardware real, simplemente aparecerá así.

-1

Lo más probable es que no funcione. malloc no puede reorganizar la memoria ya asignada por lo que no puede hacer un bloque libre continuo de 20 bytes. Solo puede solicitarle al SO que obtenga otra página de memoria, de la cual puede cortar 20 bytes + encabezado.

+0

Lo siento, pero hay muchas cosas malas con eso. "malloc" * puede * memoria 'realloc', y en diversas circunstancias puede devolverle la misma ubicación. Esto se debe a que a menudo las implementaciones de malloc te dan más memoria de la que pides (por ejemplo, un esquema popular es dividir la memoria en cubos, y cada segmento contiene regiones de memoria de un cierto tamaño, luego malloc te dará un elemento de un contenedor que puede contener al menos el tamaño requerido). Además, malloc no solicitará al SO una página nueva para tamaños pequeños, solo si los depósitos están vacíos. Sin embargo, generalmente se pregunta al asignar grandes tamaños. – DarkDust

+1

@DarkDust: estoy de acuerdo en que la respuesta aún no está bien explicada, pero su deconstrucción también deja bastante que desear. No puedo interpretar 'malloc can realloc memory, y en diversas circunstancias puede devolverle la misma ubicación' como una declaración significativa que describe con precisión el comportamiento de malloc. –

1

Desde el norma ISO C99:

7.20.3 funciones de gestión de memoria
El orden y la contigüidad de almacenamiento asignado por sucesivas llamadas al calloc, malloc, y las funciones REALLOC no está especificado . El puntero devuelto si la asignación tiene éxito se alinea adecuadamente para que pueda asignarse a un puntero a cualquier tipo de objeto y luego utilizarse para acceder a dicho objeto o una matriz de dichos objetos en el espacio asignado (hasta que el espacio se desasigna explícitamente) . La duración de un objeto asignado se extiende desde la asignación hasta la desasignación. Cada una de esas asignaciones arrojará un puntero a un objeto disjuntado de cualquier otro objeto. El puntero devolvió los puntos al inicio (dirección de byte más bajo) del espacio asignado. Si no se puede asignar el espacio, se devuelve un puntero nulo. Si el tamaño del espacio solicitado es cero, el comportamiento está definido por la implementación: se devuelve un puntero nulo o el comportamiento es como si el tamaño fuera un valor distinto de , excepto que el puntero devuelto no se debe usar para acceder a un objeto.

7.20.3.3 función
La función malloc El malloc asigna espacio para un objeto cuyo tamaño está especificado por size y cuyo valor es indeterminado.

En otras palabras, si solicita espacio para un objeto de 20 bytes, obtendrá suficiente espacio para caber en un objeto de 20 bytes.

7

La llamada a malloc, o bien tener éxito en la devolución de un bloque contiguo lógicamente de la memoria del espacio de memoria de almacenamiento dinámico de su programa igual al tamaño solicitado o se producirá un error con un puntero NULL. "Lógicamente contigua" significa que con un malloc de este tipo:

int *ip;  /* Nothing yet allocated (other than the size of a pointer... */ 
int ar[100]; /* 100 ints on the STACK */ 
ip = (int *)malloc(sizeof ar); /* if that succeeds, 100 ints on the HEAP */ 

asignará espacio para 100 enteros de su sistema operativo en el montón y devolver NULL o el puntero. Por separado, el arreglo ar se asigna en la PILA. Cada matriz se distribuirá con todas las entradas lógicamente una al lado de la otra, al menos hasta donde sabe su programa. Si no estuvieran uno al lado del otro, no sería posible direccionar estos bloques como matrices con la notación array[offset] o con la aritmética del puntero.

A continuación, puede acceder a cualquiera PILA o montón bloques de memoria con un acceso a la matriz o el acceso puntero indistintamente como esto:

ip[2]=22;  /* the second element of ip[] is '22' */ 
*(ar+33)=3333; /* the 33 element of ar is '3333' */ 

i=*(ip+2);  /* assign using pointers */ 
j=ar[33];  /* assign using array offsets */ 

Si el bloque de memoria devuelto por malloc no eran lógicamente contigua a su programa, lo haría no ser capaz de acceder al bloque con aritmética de puntero o subscripción de matriz.

Detrás de escena, su sistema operativo puede mover otros bloques de memoria que se pueden mover, usar memoria virtual, intercambiar otros elementos a la memoria virtual, etc., para aumentar el HEAP asignado a su programa. Malloc puede ser una llamada muy rápida o muy cara, dependiendo de qué más esté sucediendo en ese sistema y el espacio HEAP asignado a su programa.

memoria de pila (la parte visitada con sistema dinámico de llamadas en C) está potencialmente sujeto a la fragmentación. Digamos que asignó la cantidad de bloques de 20 bytes donde la memoria escasea. Ahora imagina que liberas todos los otros bloques de esos bloques. Tendrá una memoria muy fragmentada ya que los bloques asignados con malloc no se pueden mover si afecta al puntero que el programa utiliza para acceder al bloque. (Se puede mover de forma transparente, pero no cuentan con que el ser eficiente.)

Si va a realizar muchas llamadas a la pila de memoria, tenga en cuenta el cambio de su lógica para utilizar realloc para crecer y reducir el tamaño de la memoria, según sea necesario. Un gran 'gotcha' con realloc es que el puntero a sus datos existentes puede cambiar, así que solo use 1 puntero a él. Realloc permite que el sistema operativo mueva los datos según sea necesario para ajustarse mejor a lo que está disponible en HEAP. Evitará (en su mayoría) el potencial de fragmentación de la memoria de esa manera.

Para bloques de 20 bytes rápidos, considere el uso de la pila. Esto es para lo que sirve. Consulte this SO post para ver las características de STACK vs HEAP.

Leer el C Guide of calloc, malloc, realloc, free para obtener más información.

+0

'realloc' copiará el contenido del primer bloque al segundo si no puede expandir directamente el bloque. Si NO QUIERE que se copie, no llame a 'realloc' como una optimización. –

1

sistema operativo específico.

Si se trata de un sistema que tiene memoria virtual, malloc es sólo va a asignar otra página de la máquina virtual y añadirlo a su acervo, y luego la mano de la memoria que necesita. Sin embargo, el trozo de memoria dentro de la página debe ser contigua. Curiosamente, si su demanda es mayor que el tamaño de página, la memoria no tiene que estar contigua en la memoria física. Dos páginas de VM se pueden hacer contiguas, independientemente de dónde se encuentren en la memoria física.

Si se trata de un sistema que no tiene VM, entonces sí, toda la memoria que petición necesita ser contiguos en la memoria física.