Quelles sont les chances que realloc échoue?

Est-ce que cela échoue quand il manque de mémoire libre semblable à malloc ou pourrait-il y avoir d’autres raisons?

N’importe laquelle des fonctions d’allocation ( malloc , realloc , calloc et sur POSIX, posix_memalign ) pourrait échouer pour l’une des raisons suivantes et éventuellement d’autres:

  • Vous avez utilisé tout votre espace d’adressage virtuel, ou du moins la partie utilisable de celui-ci. Sur une machine 32 bits, il n’ya que 4 Go d’adresses, et 1 Go environ est réservé au kernel du système d’exploitation. Même si votre machine dispose de 16 Go de mémoire physique, un seul processus ne peut pas utiliser plus d’adresses qu’il n’en a.
  • Vous n’avez pas utilisé votre espace d’adressage virtuel, mais vous l’avez tellement fragmenté qu’aucune plage d’adresses contiguës de la taille demandée n’est disponible. Cela pourrait se produire (sur une machine 32 bits) si vous allouez avec succès 6 blocs de 512 Mo, libérez-les tous les autres, puis essayez d’allouer un bloc de 1 Go. Bien sûr, il existe de nombreux autres exemples avec des tailles de mémoire plus petites.
  • Votre ordinateur manque de mémoire physique, soit parce que votre propre programme l’a tout utilisé, soit que d’autres programmes en cours d’exécution sur cet appareil ont tout utilisé. Certains systèmes (Linux dans la configuration par défaut) s’engageront trop , ce qui signifie que malloc n’échouera pas dans cette situation, mais le système d’exploitation tuera plus tard un ou plusieurs programmes quand il réalisera qu’il n’ya pas vraiment assez de mémoire physique. Mais sur les systèmes robustes (y compris Linux avec sur-engagement désactivé), malloc échouera s’il ne rest plus de mémoire physique.

Notez que, à proprement parler, les fonctions d’allocation sont autorisées à échouer à tout moment et pour quelque raison que ce soit. Minimiser les échecs est un problème de qualité de mise en œuvre. Il est également possible que realloc échoue, même en réduisant la taille d’un object. Cela peut se produire sur des implémentations qui séparent ssortingctement les allocations par taille. Bien sûr, dans ce cas, vous pouvez simplement continuer à utiliser l’ancien object (plus grand).

Vous devriez penser à realloc comme fonctionnant de cette façon:

 void *realloc(void *oldptr, size_t newsize) { size_t oldsize = __extract_size_of_malloc_block(oldptr); void *newptr = malloc(newsize); if (!newptr) return 0; if (oldsize > newsize) oldsize = newsize; memcpy(newptr, oldptr, oldsize); free(oldptr); return newptr; } 

Une implémentation peut être capable de traiter des cas spécifiques plus efficacement que cela, mais une implémentation qui fonctionne exactement comme indiqué est correcte à 100%. Cela signifie que realloc(ptr, newsize) peut échouer à tout moment où malloc(newsize) aurait échoué; en particulier, cela peut échouer même si vous réduisez l’allocation .

Maintenant, sur les systèmes de bureau modernes, il y a de fortes raisons de ne pas essayer de malloc échecs de malloc , mais plutôt d’envelopper malloc dans une fonction (généralement appelée xmalloc ) qui termine immédiatement le programme en cas d’échec de malloc ; naturellement, le même argument s’applique à realloc . L’affaire est:

  1. Les systèmes de bureau fonctionnent souvent en mode “surcommit” où le kernel dissortingbuera avec bonheur plus d’espace d’adresse que ce qui peut être sauvegardé par RAM + swap, en supposant que le programme ne l’utilisera pas réellement. Si le programme essaie de tout utiliser, il sera forcé de se terminer. Sur de tels systèmes, malloc n’échouera que si vous épuisez l’ espace d’adressage , ce qui est peu probable sur les systèmes 32 bits et quasi impossible sur les systèmes 64 bits.
  2. Même si vous n’êtes pas en mode de sur-engagement, il est probable qu’un ordinateur de bureau dispose d’une mémoire RAM et d’un échange suffisants, bien avant que vous ne malloc échec de malloc , l’utilisateur en aura marre de son disque écrasant et mettra fin de force à votre programme.
  3. Il n’existe aucun moyen pratique de tester la reprise après une défaillance d’allocation; même si vous aviez une bibliothèque de shim capable de contrôler avec précision quels appels à malloc échoué (ces shim sont difficiles à créer, voire impossibles à créer, selon le système d’exploitation), vous devez tester l’ordre de 2 N modèles de défaillance, où N est le nombre d’appels à malloc dans votre programme.

Les arguments 1 et 2 ne s’appliquent pas (encore!) Aux systèmes embarqués ou mobiles, mais l’argument 3 est toujours valide ici.

L’argument 3 ne s’applique qu’aux programmes où les échecs d’allocation doivent être vérifiés et propagés sur chaque site d’appel. Si vous êtes assez chanceux pour utiliser le C ++ tel qu’il est destiné à être utilisé (c’est-à-dire avec des exceptions), vous pouvez vous fier au compilateur pour créer les chemins de reprise sur incident, ce qui réduira considérablement la charge de test. Et dans tous les langages de niveau supérieur qui valent la peine d’être utilisés de nos jours, vous avez à la fois des exceptions et un ramasse-miettes, ce qui signifie que vous ne pouvez pas vous inquiéter des échecs d’allocation, même si vous le vouliez.

Je dirais que la plupart de mise en œuvre spécifique. Certaines implémentations risquent fort d’échouer. Certains peuvent avoir d’autres parties du programme échouer avant que realloc ne le fasse. Soyez toujours sur la défensive et vérifiez si cela échoue.

Et souvenez-vous de libérer l’ ancien pointeur que vous avez essayé de réaffecter.

 ptr=realloc(ptr,10); 

est TOUJOURS une fuite de mémoire possible.

Toujours le faire plutôt comme ça:

 void *tmp=ptr; if(ptr=realloc(ptr,10)==NULL){ free(tmp); //handle error... } 

Vous avez deux questions.

Les chances que malloc ou realloc échouent sont négligeables sur la plupart des systèmes modernes. Cela se produit uniquement lorsque vous manquez de mémoire virtuelle. Votre système ne parviendra pas à accéder à la mémoire et non à la réserver.

Les échecs réels realloc et malloc sont presque égaux. En outre, la seule raison pour laquelle realloc peut échouer est que vous lui donnez un argument erroné, à savoir une mémoire qui n’avait pas été allouée avec malloc ou realloc ou qui était auparavant free d.

Edit: Compte tenu du commentaire de R. Oui, vous pouvez configurer votre système de manière à ce qu’il échoue lors de l’allocation. Mais tout d’abord, autant que je sache, ce n’est pas la valeur par défaut. Il a besoin de privilèges pour être configuré de cette manière et, en tant que programmeur d’application, vous ne pouvez compter sur rien. Deuxièmement, même si votre système est configuré de cette manière, cela ne provoquera une erreur que lorsque votre espace d’échange disponible sera épuisé. Généralement, votre machine sera inutilisable bien avant cela: elle effectuera des calculs mécaniques sur votre disque dur (échange de AKA).