Le bloc de mémoire renvoyé par malloc (et ses cousins) est-il initialisé à zéro?

J’ai écrit un code à tester pour tester la gestion de la mémoire de Linux et de Windows. Juste pour d’autres tests, je suis allé de l’avant et j’ai vérifié quelles sont les valeurs présentes dans la mémoire renvoyée par malloc ().

Les valeurs renvoyées sont toutes 0 (zéro). J’ai lu la page de manuel de malloc, vérifiée sous Windows et Linux, mais je ne parviens pas à trouver la raison de ce comportement . Selon la page de manuel le

La fonction malloc () alloue des octets de taille et renvoie un pointeur sur la mémoire allouée. La mémoire n’est pas initialisée.

Pour effacer le segment de mémoire, il faut utiliser manuellement memset ().

#include  #include  #include  #include  #include  int eat(long total,int chunk){ long i; for(i=0;i<total;i+=chunk){ short *buffer=malloc(sizeof(char)*chunk); if(buffer==NULL){ return -1; } printf("\nDATA=%d",*buffer); memset(buffer,0,chunk); } return 0; } int main(int argc, char *argv[]){ int i,chunk=1024; long size=10000; printf("Got %ld bytes in chunks of %d...\n",size,chunk); if(eat(size,chunk)==0){ printf("Done, press any key to free the memory\n"); getchar(); }else{ printf("ERROR: Could not allocate the memory"); } } 

Peut-être que je manque quelque chose. Le code est adapté d’ ici

EDIT: Le problème a été résolu ici pour la sortie spécifique de GCC. Je crois que le système d’exploitation Windows suivrait également les mêmes procédures.

La mémoire renvoyée par malloc() n’est pas initialisée, ce qui signifie qu’elle peut être n’importe quoi. Ce peut être zéro, et peut-être pas; “non initialisé” signifie que cela pourrait être n’importe quoi (zéro inclus). Pour obtenir une page zéro garantie, utilisez calloc() .

La raison pour laquelle vous voyez des pages à zéro (de toute façon sous Linux) est que si une application demande de nouvelles pages, celles-ci sont mises à zéro par le système d’exploitation (ou plus précisément par des images d’une page fixe). page zéro globale ‘). Mais si malloc() utilise de la mémoire déjà allouée à l’application qui a été libérée depuis (plutôt que d’étendre le tas), vous pouvez voir des données non nulles. Notez que la mise à zéro des pages fournies par le système d’exploitation est un trait spécifique au système d’exploitation (principalement pour la sécurité, de sorte qu’un processus ne se termine pas par des pages contenant des données provenant d’un autre processus).

Vous avez demandé une source pour get_free_page zeroing la page: qui dit: get_free_page() prend un paramètre, une priorité. … Il free_page_list une page de la free_page_list , met à jour mem_map , met la page à zéro et renvoie l’adresse physique de la page. ‘ Voici un autre article qui explique bien, et explique aussi pourquoi utiliser calloc() est meilleur que malloc() + memset() .

Notez que vous ne vérifiez pas la totalité du bloc alloué pour zéro. Vous voulez quelque chose comme ça (non testé):

 int n; char nonzero=0; char *buffer=malloc(sizeof(char)*chunk); if(buffer==NULL){ return -1; } for (n = 0; n 

Vous avez absolument raison. Ce comportement n’est pas garanti par la norme de langage C.

Ce que vous observez pourrait simplement être un hasard (vous ne contrôlez que quelques octets dans chaque allocation), ou cela peut être un artefact de la façon dont votre bibliothèque d’exécution C et votre système d’exploitation allouent de la mémoire.

Avec cette déclaration:

 printf("\nDATA=%d",*buffer); 

Vous ne contrôlez que la première sizeof(short) quantité d’octets qui vient d’être malloc() (généralement deux (2) octets).

De plus, la première fois que vous aurez la chance d’obtenir tous les zéros, mais après que votre programme ait exécuté (et utilisé) la mémoire de tas, le contenu-après- malloc() sera indéfini.

la fonction d’allocation de mémoire: calloc () renverra un pointeur sur la nouvelle zone et définira tous les octets sur zéro.

La fonction d’allocation de mémoire: realloc () renverra un pointeur sur une zone (éventuellement nouvelle) et copiera les octets de l’ancienne zone. La nouvelle zone sera la «nouvelle» longueur demandée

La fonction d’allocation de mémoire malloc renverra un pointeur sur la nouvelle zone mais ne définira pas les octets à une valeur spécifique

Les valeurs renvoyées sont toutes 0 (zéro).

Mais ce n’est pas garanti. C’est parce que vous exécutez simplement votre programme. Si vous faites un malloc, remplissez au hasard et libérez beaucoup, vous commencerez à remarquer que la mémoire précédemment libérée est réutilisée, ainsi vous commencerez à obtenir des morceaux non nuls dans vos mallocs.

Oui, vous avez raison. Malloc () n’initialise pas les valeurs par zéro. Il tire arbitrairement la quantité de mémoire qu’il lui est demandé d’allouer à partir du tas, ce qui signifie essentiellement qu’il pourrait y avoir quelque chose déjà stocké à l’intérieur. Vous devriez donc utiliser seulement malloc (), où vous êtes certain que vous allez définir une valeur. Si vous faites de l’arithmétique dès la sortie de la boîte, vous obtiendrez peut-être des résultats médiocres (j’ai déjà personnellement plusieurs fois expérimenté cela, vous allez avoir du code fonctionnel avec des résultats parfois fous).

Donc, définissez des choses que vous ne définissez pas sur zéro avec memset (). Ou mon conseil est d’utiliser calloc() . Calloc, autre que malloc, initialise les valeurs à zéro. Et pour autant que je sache, plus rapide que la combinaison de malloc () et memset (), malloc seul est plus rapide que calloc. Donc, essayez de trouver la version la plus rapide possible au moment du problème en vous gardant en mémoire.

Regardez aussi cet article ici: les rendements de multiplication masortingcielle-vectorielle de MPI corrigent parfois des valeurs parfois étranges . La question était différente, mais la cause était la même.