2012-05-24 9 views
6

estoy en una cruz scratchbox compilar medio ambiente y tener esta¿Por qué no aumenta la huella de memoria de este programa?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main() 
{ 
    int * ptr; 
    int i=0; 

    while(1) 
    { 
     ptr = (int*)malloc(10485760 * sizeof(int)); 

     if(ptr == NULL) 
     { 
      printf("Could not malloc\n"); 
      exit(1); 
     } 

     else 
     { 
      printf("Malloc done\n"); 
      for (i = 0 ; i <= 10485759 ; i++) 
      { 
       ptr[i] = i ; 
      } 
      sleep (5); 
      continue; 
     } 
    } 
} 

Cuando ejecuto el binario y hago

ps -p pid -o cmd,rss,%mem 

no veo ningún aumento en el consumo de memoria del proceso. ¿Porqué es eso?

+0

porque la memoria está asignada de una vez al principio? –

+3

@arasmussen Dentro de un ciclo 'while'. –

+0

Quizás el compilador vea que ya no tiene un control sobre ese puntero (porque usted escribe más de una vez ptr) y está limpiando después de eso para usted? ¿O tal vez lleva mucho tiempo ejecutar diez millones de iteraciones? –

Respuesta

5

Probablemente haya construido muy optimizado.

En la mayoría de los sistemas modernos, gcc sabe que malloc devuelve un puntero sin alias. Es decir, nunca devolverá el mismo puntero dos veces y nunca devolverá un puntero que haya guardado 'en vivo' en otro lugar.

Me parece muy difícil de imaginar, pero es posible que malloc se llame una vez y su valor de retorno se utilice una y otra vez. Las razones son:

Sabe que su memoria es una tienda muerta. es decir: usted escribe, pero nunca se lee. Se sabe que el puntero no tiene alias, por lo que no se ha escapado para leerse en otro lugar y no está marcado como volátil. Su bucle for/sí/puede ser desechado.

En ese momento podría usar la misma memoria una y otra vez.

Ahora, esta es la razón por la que me resulta difícil de creer: ¿cuánto sabe gcc sobre malloc? Malloc podría tener cualquier tipo de efectos secundarios como incrementar una 'cantidad de veces' global 'para' pintar mi habitación con un tono aleatorio de azul '. Parece realmente extraño que abandone la llamada y suponga que es libre de efectos secundarios. Demonios, 'malloc' podría implementarse para devolver NULL cada centésima llamada (tal vez no exactamente según las especificaciones, pero quién puede decir).

Lo que NO está haciendo es liberarlo en su nombre. Eso va más allá de lo que "podría" saber y en el territorio de "hacer cosas que simplemente no se permite". Se te permite perder memoria, aunque pueda ser flojo.

2 cosas serían útiles aquí: 1) Compile environmenet: que os, compilador y banderas de línea de comando.

y 2) desmontaje del binario final. (objdump o del compilador)

+0

_Solo ¿cuánto sabe gcc sobre malloc? _ Gcc tiene permitido saber todo sobre 'malloc()', porque C Standard especifica el comportamiento de esa función. – mlp

-2

Su compilador lo está ayudando liberando la memoria asignada (asumiendo que la versión optimizada de su código incluso hace el malloc) cuando se da cuenta de que no la está usando. Puede intentar imprimir el valor del puntero (printf ("0x% x", ptr);) - Sospecho que obtendrá valores repetitivos. Una verificación más confiable escribiría una cadena de bits conocida en la memoria, después de haber buscado para ver si la memoria asignada ya contiene esa cadena. En otras palabras, en lugar de escribir i, escriba 0xdeadbeef0cabba6e una y otra vez, después de verificar para ver si ese patrón de bits ya está en el espacio que ha asignado.

+0

C normalmente no va a hacer ese tipo de recolección de basura en tiempo de ejecución. Pero es interesante pensar en lo que un compilador * podría * hacer. Ninguno de 'ptr [i]' se lee alguna vez, por lo que esa asignación podría ser eliminada. Entonces, ninguna parte de la memoria asignada por 'malloc' se usa de ninguna manera, por lo que en el principal podría eludirse (si estamos seguros de que la" cantidad de memoria asignada "no es una propiedad de corrección que deba conservarse). Sin embargo, el primero es probablemente complicado con aliasing, y me sorprendería si algún compilador de C existente hace el segundo; no estoy seguro de que sea una transformación válida de todos modos. – Edmund

+0

Nunca sugerí que hubiera ningún tipo de recolección de basura en absoluto. La especificación C permite cualquier optimización bajo la única condición de que el resultado final no tenga una diferencia funcional con respecto a la definida por la definición de la máquina abstracta C. (TEN EN CUENTA que no estamos hablando de una máquina virtual en el sentido de Java, sino en el sentido de que la especificación C define una máquina abstracta como un mecanismo para definir el comportamiento del código compilado). Sería bueno para el optimizador eliminar las asignaciones del código anterior por completo. – Sniggerfardimungus

+0

"Recolección de basura" es el proceso de tomar decisiones, en tiempo de ejecución, sobre cuándo se puede liberar la memoria sin referencia. No estamos hablando de una decisión de tiempo de ejecución aquí, sino de un efecto en tiempo de compilación al notar que los datos asignados y escritos nunca se usan. – Sniggerfardimungus

2

rss y% mem son ambos en términos de "memoria física utilizada por el proceso en este momento". Tiene muchas oportunidades para enviar cosas. Prueba agregar vsz. Apuesto a que crece como lo esperabas.

+0

Te molesta. Si asumes lo que dije a continuación sobre que el compilador puede tirar el bucle de asignación como una tienda muerta, esta memoria se reservaría pero nunca se comprometería y podría repetirse hasta que se agote el espacio de direcciones; sin cometer un byte en realidad. :) – Joe

Cuestiones relacionadas