11
votes

Que ferait la ré-liste s'il n'y a pas d'espace séquentiel de mémoire?

realloc est utilisé pour réaffecter la mémoire de manière dynamique.

Supposons que j'ai alloué 7 octets à l'aide de la fonction malloc et que je veux maintenant l'étendre à 30 octets.

Que se passera-t-il en arrière-plan s'il n'y a pas de séquentiel (continuellement dans une seule rangée) de 30 octets dans la mémoire?

Y a-t-il une erreur ou une mémoire sera allouée en pièces?


0 commentaires

5 Réponses :


1
votes

du Page Man :

realloc () renvoie un pointeur sur le mémoire nouvellement attribuée, qui est convenablement aligné pour tout type de variable et peut être différent de PTR, ou null si la demande échoue.

Ainsi, en d'autres termes, de détecter l'échec, vérifiez simplement si le résultat était null.

Edit: Comme indiqué dans le commentaire, si l'appel échoue, la mémoire originale n'est pas libérée.


1 commentaires

La peine de noter à partir de la page d'homme: Si Realloc () échoue, le bloc d'origine est laissé intact; Ce n'est pas libéré ni déplacé.



6
votes

realloc ne réussira que s'il peut renvoyer une mémoire contiguë ("séquentielle" dans vos mots). Si aucun bloc de ce type n'existe, il retournera null .


6 commentaires

@Mark - La mémoire originale est laissée inchangée. Un bug commun dans ce contexte est 'x = realloc (x)' - vous devez faire "newx = realloc (x)" pour éviter de fuir l'erreur x sur erreur.


@Steve townsend - c'est seulement quand il échoue de rite? Quand il réussit, il libère le pointeur d'origine. Et whos marque dans cette page? O_o


Je suppose qu'il y avait une erreur. Le premier commentaire a été montré à partir de l'utilisateur Sharptooth et il est désormais modifié, bien que les deux soient adressés à marquer. Était-ce un bug? :-P


@Praveen - Mon commentaire a été adressé à un commentaire précédent maintenant supprimé. Oui, l'utilisation que j'ai montré est toujours un bug. Lorsqu'il réussit, il libère le pointeur d'origine (ou le retourne à nouveau pour que vous puissiez l'utiliser si un bloc plus important peut être ancré là-bas).


@Steve: Ce n'est pas un bogue si vous le suivez avec si (! X) quitte (1); :-)


@R - Bon point. Dans de nombreuses applications, je suis sûr que l'échec de l'allocation de mémoire épellerait de toute façon une mort imminente.



1
votes

En général, cela dépend de la mise en œuvre. Sur x86 (-64) Linux, je pense que la norme Doug Lea Malloc Algorithme allouera toujours au minimum une page standard X86 (4096 octets), donc pour le scénario que vous avez décrit ci-dessus, il suffirait de réinitialiser les limites pour accueillir les octets supplémentaires. . En ce qui concerne, par exemple, réaffectant un tampon de 7bytes à PAGE_SIZE + 1 Je crois qu'il va essayer d'affecter la page suivante contiguë disponible

la peine de lire ce qui suit, si vous développez sous Linux: p>

Par défaut, Linux suit une stratégie optimiste de l'allocation de mémoire. Cela signifie que lorsque MALLOC () renvoie non-NULL, rien ne garantit que la mémoire est réellement disponible. C'est un vraiment mauvais bug. Au cas où il s'avère que le système est hors de mémoire, un ou plusieurs processus seront tués par le célèbre tueur d'OOM. Dans le cas où Linux est utilisé dans des circonstances où il serait moins souhaitable de perdre soudainement certains processus choisis au hasard, et de plus, la version du noyau est suffisamment récente, on peut éteindre ce comportement sur la surmontation en utilisant une commande comme: p>

# echo 2 > /proc/sys/vm/overcommit_memory


0 commentaires

11
votes

realloc code> fonctionne derrière les scènes approximativement comme ceci:

  • S'il y a suffisamment d'espace libre derrière le bloc actuel pour remplir la demande, étendez le bloc actuel et renvoyez un pointeur au début du bloc. LI>
  • sinon s'il y a un bloc libre assez important ailleurs, puis allocation de ce bloc, copiez les données de l'ancien bloc sur, libérer l'ancien bloc et renvoyer un pointeur au début du nouveau bloc LI>
  • sinon signalez l'échec en retournant null code>. li> ul>

    Ainsi, vous pouvez tester une échec en testant pour null code>, mais soyez conscient que vous ne écrasez pas trop l'ancien pointeur Trop tôt: P>

    int* p = malloc(x);
    /* ... */
    p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */
    /* Correct way: */
    {
      int* temp = realloc(p, y);
      if (NULL == temp)
      {
        /* Handle error; p is still valid */
      }
      else
      {
        /* p now possibly points to deallocated memory. Overwrite it with the pointer
           to the new block, to start using that */
        p = temp;
      }
    }
    


2 commentaires

Est-ce le realloc fonctionne pour toutes les implémentations?


@CoolGuy: Certaines implémentations peuvent ne pas (être capable de) faire cette première étape d'étendre le bloc actuel, mais sinon il s'agit du comportement observable de realloc pour toutes les implémentations.



0
votes

FreeBSD et Mac OS X ont la fonction REALLOCF () qui libérera le pointeur transduit lorsque la mémoire demandée ne peut pas être allouée (voir homme Realloc).


1 commentaires

Plutôt que d'utiliser cela, cela ferait beaucoup plus de sens de simplement écrire votre propre fonction pour le faire si vous voulez vraiment ce comportement. Mais je ne peux pas imaginer que cela soit très utile - il élimine des données probablement précieuses.