¿Por qué malloc inicializa los valores a 0 en gcc?

 C Programming >> Programación C >  >> Tags >> GCC
¿Por qué malloc inicializa los valores a 0 en gcc?


Tal vez sea diferente de una plataforma a otra, pero


cuando compilo usando gcc y ejecuto el siguiente código, siempre obtengo 0 en mi ubuntu 11.10.


#include <stdio.h>
#include <stdlib.h>
int main()
{
double *a = malloc(sizeof(double)*100)
printf("%f", *a);
}

¿Por qué malloc se comporta así aunque haya calloc?


¿No significa que hay una sobrecarga de rendimiento no deseada solo para inicializar los valores a 0, incluso si no quiere que sea a veces?



EDITAR:Oh, mi ejemplo anterior no estaba iniciando, pero usó un bloque "nuevo".


Lo que precisamente estaba buscando era por qué lo inicializa cuando asigna un bloque grande:


int main()
{
int *a = malloc(sizeof(int)*200000);
a[10] = 3;
printf("%d", *(a+10));
free(a);
a = malloc(sizeof(double)*200000);
printf("%d", *(a+10));
}
OUTPUT: 3
0 (initialized)

¡Pero gracias por señalar que hay una razón de SEGURIDAD al hacer una mallocación! (Nunca pensé en eso). Seguro que tiene que inicializarse a cero cuando se asigna un bloque nuevo o el bloque grande.


Respuestas:


Respuesta corta:


No es así, simplemente pasa a ser cero en su caso.
(Además, su caso de prueba no muestra que los datos sean cero. Solo muestra si un elemento es cero).



Respuesta larga:


Cuando llamas a malloc() , ocurrirá una de estas dos cosas:



  1. Recicla la memoria que se asignó previamente y se liberó del mismo proceso.

  2. Solicite nuevas páginas del sistema operativo.


En el primer caso, la memoria contendrá datos sobrantes de asignaciones anteriores. Entonces no será cero. Este es el caso habitual cuando se realizan pequeñas asignaciones.


En el segundo caso, la memoria será del sistema operativo. Esto sucede cuando el programa se queda sin memoria, o cuando solicita una asignación muy grande. (como es el caso en su ejemplo)


Aquí está el truco:La memoria procedente del sistema operativo se pondrá a cero por seguridad motivos.*


Cuando el sistema operativo le brinda memoria, podría haberse liberado de un proceso diferente. De modo que esa memoria podría contener información confidencial, como una contraseña. Entonces, para evitar que lea dichos datos, el sistema operativo los pondrá a cero antes de dárselos.


*Observo que el estándar C no dice nada sobre esto. Esto es estrictamente un comportamiento del sistema operativo. Por lo tanto, esta reducción a cero puede o no estar presente en sistemas donde la seguridad no es una preocupación.



Para dar más antecedentes de rendimiento a esto:


Como @R. menciona en los comentarios, esta reducción a cero es la razón por la que siempre debe usar calloc() en lugar de malloc() + memset() . calloc() puede aprovechar este hecho para evitar un memset() separado .



Por otro lado, esta reducción a cero es a veces un cuello de botella en el rendimiento. En algunas aplicaciones numéricas (como la FFT fuera de lugar), debe asignar una gran cantidad de memoria temporal. Úselo para realizar cualquier algoritmo, luego libérelo.


En estos casos, la reducción a cero es innecesaria y equivale a gastos generales puros.


El ejemplo más extremo que he visto es una sobrecarga de puesta a cero de 20 segundos para una operación de 70 segundos con un búfer temporal de 48 GB. (Aproximadamente un 30 % de sobrecarga).
(Concedido:la máquina carecía de ancho de banda de memoria).


La solución obvia es simplemente reutilizar la memoria manualmente. Pero eso a menudo requiere romper las interfaces establecidas. (especialmente si es parte de una rutina de biblioteca)