c linux-kernel malloc non-deterministic

¿Por qué Malloc es realmente no determinista?(Linux/Unix)



linux-kernel non-deterministic (10)

no se garantiza que Malloc devuelva la memoria de 0''ed. La sabiduría convencional no es solo eso, sino que los contenidos de la memoria malloc son en realidad no deterministas , por ejemplo, openssl los usó para la aleatoriedad extra .

Sin embargo, hasta donde yo sé, malloc está construido sobre brk / sbrk , que "devuelve" memoria de 0''ed. Puedo ver por qué el contenido de lo que devuelve malloc puede ser distinto de 0 , por ejemplo, de memoria previamente libre , pero ¿por qué no serían deterministas en un software de subproceso único "normal"?

  1. Es la sabiduría convencional realmente cierta (suponiendo que el mismo binario y las bibliotecas)
  2. Si es así, ¿por qué?

Editar Varias personas respondieron explicando por qué la memoria puede ser diferente de 0, lo que ya expliqué en la pregunta anterior. Lo que estoy preguntando es por qué el programa que usa los contenidos de lo que devuelve malloc puede no ser determinista, es decir, por qué podría tener un comportamiento diferente cada vez que se ejecuta (suponiendo que el mismo binario y las mismas bibliotecas). El comportamiento no determinista no está implícito en los no-0. Para decirlo de otra manera: por qué podría tener diferentes contenidos cada vez que se ejecuta el binario.


Creo que la suposición de que no es determinista es completamente errónea, particularmente cuando pides un contexto sin hilos. (En un contexto enhebrado debido a la programación de alea podría tener algo de no determinismo).

Solo pruébalo. Cree una aplicación secuencial y determinista que

  • hace un montón de asignaciones
  • llena la memoria con un patrón, por ejemplo, llénelo con el valor de un contador
  • liberar cada segundo de estas asignaciones
  • asignar nuevamente la misma cantidad
  • ejecutar estas nuevas asignaciones y registrar el valor del primer byte en un archivo (como los números de texto uno por línea)

ejecuta este programa dos veces y registra el resultado en dos archivos diferentes. Mi idea es que estos archivos serán idénticos.


Existe un ecosistema completo de programas que viven dentro de una memoria de computadora y no se puede controlar el orden en que se producen mallocs y free.

Imagine que la primera vez que ejecuta su aplicación y malloc () algo, le da una dirección con algo de basura. Luego, su programa se apaga, su sistema operativo marca esa área como libre. Otro programa lo toma con otro malloc (), escribe muchas cosas y luego se va. Si vuelve a ejecutar su programa, es posible que malloc () le proporcione la misma dirección, pero ahora hay una basura diferente allí, que el programa anterior podría haber escrito.

En realidad no conozco la implementación de malloc () en ningún sistema y no sé si implementa algún tipo de medida de seguridad (como aleatorizar la dirección devuelta), pero no lo creo.

Es muy determinista.


Incluso el código de un solo subproceso puede hacer malloc, luego liberarlo y luego volver a utilizar la memoria que no sea cero.


Incluso en programas de subproceso único "normales", la memoria se libera y se reasigna muchas veces. Malloc volverá a su memoria que había usado antes.


La forma más sencilla en que puedo pensar al poner la respuesta es así:

Si estoy buscando espacio en la pared para pintar un mural, no me importa si es blanco o si está cubierto con graffiti antiguo, ya que voy a imprimarlo y pintarlo. Solo me importa si tengo suficientes pies cuadrados para acomodar la imagen, y me importa que no estoy pintando sobre un área que le pertenece a otra persona.

Así es como piensa Malloc. Poner a cero la memoria cada vez que finaliza un proceso sería un esfuerzo computacional desperdiciado. Sería como volver a cebar la pared cada vez que termine de pintar.


La memoria devuelta por malloc no se ha puesto a cero (o, mejor dicho, no se garantiza que esté puesta a cero) porque no es necesario. No existe riesgo de seguridad al reutilizar la memoria no inicializada extraída del espacio de direcciones o del grupo de páginas de su propio proceso. Ya sabes que está ahí, y ya sabes el contenido. Tampoco hay ningún problema con los contenidos en un sentido práctico, porque de todos modos los sobrescribirá.

Incidentalmente, la memoria devuelta por malloc se pone a cero en la primera asignación, porque un kernel del sistema operativo no puede permitirse el riesgo de proporcionar a un proceso los datos que otro proceso tenía previamente. Por lo tanto, cuando el sistema operativo falla en una página nueva, solo proporciona una que se ha puesto a cero. Sin embargo, esto no tiene ninguna relación con malloc .

(Un poco fuera de tema: la cuestión de seguridad de Debian que mencionó tenía algunas implicaciones más que utilizar memoria no inicializada para la aleatoriedad. Un empaquetador que no estaba familiarizado con el funcionamiento interno del código y no sabía las implicaciones precisas parcheadas en un par de lugares que Valgrind había informado, presumiblemente con buena intención, pero con un efecto desastroso. Entre estos estaba el "azar de la memoria no iniciada", pero de lejos no era el más severo).


Los valores iniciales de la memoria devueltos por malloc no están especificados, lo que significa que las especificaciones de los lenguajes C y C ++ no imponen restricciones sobre qué valores se pueden devolver. Esto hace que el lenguaje sea más fácil de implementar en una variedad de plataformas. Si bien podría ser cierto que en Linux malloc se implementa con brk y sbrk y la memoria debe ponerse a cero (ni siquiera estoy seguro de que esto sea necesariamente cierto, por cierto), en otras plataformas, quizás una plataforma integrada, no hay razón por la cual este debería ser el caso. Por ejemplo, un dispositivo integrado podría no querer poner a cero la memoria, ya que hacerlo cuesta ciclos de CPU y, por lo tanto, potencia y tiempo. Además, en aras de la eficiencia, por ejemplo, el asignador de memoria podría reciclar bloques que se habían liberado previamente sin ponerlos a cero primero. Esto significa que incluso si la memoria del sistema operativo inicialmente se ha reducido a cero, no es necesario que la memoria de malloc sea.

La sabiduría convencional de que los valores no son deterministas es probablemente buena, porque te obliga a darte cuenta de que cualquier memoria que recuperes puede tener datos basura que podrían bloquear tu programa. Dicho esto, no debes asumir que los valores son verdaderamente aleatorios. Sin embargo, debes darte cuenta de que los valores devueltos no serán mágicamente lo que deseas. Usted es responsable de configurarlos correctamente. Asumir que los valores son verdaderamente aleatorios es una idea realmente mala, ya que no hay nada que sugiera que lo sean.

Si desea memoria que está garantizada para ser puesta a cero, utilice calloc lugar.

¡Espero que esto ayude!


Malloc no garantiza la imprevisibilidad ... simplemente no garantiza la previsibilidad.

Ej. Considere eso

return 0;

Es una implementación válida de malloc.


No hay garantía de que brk / sbrk devuelva 0ed-out data; este es un detalle de implementación. En general, es una buena idea para un SO hacer eso para reducir la posibilidad de que la información sensible de un proceso encuentre su camino en otro proceso, pero nada en la especificación dice que será el caso.

Además, el hecho de que malloc se implemente sobre brk / sbrk también depende de la implementación, e incluso puede variar según el tamaño de la asignación; por ejemplo, grandes asignaciones en Linux tradicionalmente han usado mmap en / dev / zero en su lugar.

Básicamente, no puede confiar en regiones malloc() ed que contengan basura ni en que sea all-0, y ningún programa debe asumir una cosa u otra al respecto.


malloc se define en muchos sistemas que se pueden programar en C / C ++, incluidos muchos sistemas que no son UNIX, y muchos sistemas que carecen por completo del sistema operativo. Requerir que malloc a cero la memoria va en contra de la filosofía de C de ahorrar CPU tanto como sea posible.

El estándar proporciona un calloc cero que puede usarse si necesita poner a cero la memoria. Pero en los casos en que planea inicializar la memoria usted mismo tan pronto como la obtiene, los ciclos de CPU pasados ​​asegurándose de que el bloque se reduzca a cero son un desperdicio; La norma C tiene como objetivo evitar este desperdicio tanto como sea posible, a menudo a expensas de la previsibilidad.