Comment gérer le realloc quand il échoue en raison de la mémoire?
Question dit tout cela, mais voici un exemple:
typedef struct mutable_t{
int count, max;
void **data;
} mutable_t;
void pushMutable(mutable_t *m, void *object)
{
if(m->count == m->max){
m->max *= 2;
m->data = realloc(m->data, m->max * sizeof(void*));
}
//how to handle oom??
m->data[m->count++] = object;
}
Comment puis-je gérer à court de mémoire et pas NULL toutes mes données?
edit - nous allons supposer qu'il y a quelque chose qui pourrait être fait par exemple de libérer de la mémoire quelque part, ou au moins de dire à l'utilisateur "vous ne pouvez pas le faire - que vous êtes hors de la mémoire". Idéalement, je voudrais quitter ce qui a été alloué.
dépend fortement de l'application... mais une chose est sûre, un OOM est assez critique.
connexes: stackoverflow.com/questions/1941323/...
Juste pour ajouter quelques réponses ici, une idée de comment gérer l'échec d'une
if (!m->data) { log("s'il vous Plaît mettre à niveau vers la version 64 bits"); abort(); }
connexes: stackoverflow.com/questions/1941323/...
Juste pour ajouter quelques réponses ici, une idée de comment gérer l'échec d'une
realloc()
(dans votre cas) serait de faire m->max /= 4; m->max *= 3;
et essayez de l'appeler realloc()
à nouveau pour voir si nous pouvons encore nous serrer un peu plus d'octets. Vous pouvez même essayer une couple de fois avec, successivement, de plus petites tailles, mais à un certain point, il ne sera pas la peine.if (!m->data) { log("s'il vous Plaît mettre à niveau vers la version 64 bits"); abort(); }
OriginalL'auteur Nick Van Brunt | 2009-12-31
Vous devez vous connecter pour publier un commentaire.
La technique standard est d'introduire une nouvelle variable pour contenir le retour de realloc. Il suffit alors de remplacer votre variable d'entrée si elle réussit:
Et puis quoi? Vous n'avez pas essayez d'augmenter la taille de votre tableau pour le plaisir, vous avez réellement besoin de cela pour une raison.
l'échec de l'opération. Selon la logique de l'application, ce sera à elle de décider comment les récupérer (c'est peut-être un serveur et qu'il va échouer la demande, mais continuer à exécuter d'autres demandes). Mais cela ressemble à un faible niveau de la bibliothèque de code qui ne doit pas obliger un out-of-politique de mémoire de l'application.
Si c'était un gros redimensionner, vous pouvez essayer de faire une petite redimensionner et de voir si vous aurez de par. Sinon, vous devriez probablement imprimer un message d'erreur "manque de mémoire" et à la sortie. Ou vous pouvez nous retourner un code d'erreur, et l'appelant peut essayer de libérer de la mémoire nécessaire et essayer de nouveau, si possible. Récupération à partir d'une erreur de mémoire est possible, dans certains cas, même si il n'est pas probable dans la plupart des.
si tmp est NULL, alors il n'a pas d'importance (
free(NULL)
dans tous les malloc implémentations). Si tmp n'est pas NULL, alors oui, vous avez besoin gratuit, mais vous devez le libérer au bon moment. orig = malloc(taille) ... tmp = realloc(orig, newsize) if (tmp == NULL) { free(orig); ... donner ... } else { orig = tmp; } ... gratuit(orig);OriginalL'auteur R Samuel Klatchko
La stratégie sur que faire quand
realloc()
échoue dépend de votre application. La question est trop générique pour répondre à tous les cas possibles.Quelques autres remarques:
Ne jamais faire:
Si
realloc()
échoue, vous perdez l'origine de pointeur, etrealloc()
ne pasfree()
la mémoire d'origine, de sorte que vous obtiendrez une fuite de mémoire. Au lieu de cela, faire:Deuxième point que je veux faire est mineur et ne peut être que critique, mais c'est bon à savoir quand même: augmenter la mémoire allouée par un facteur de
f
est bon. Disons que vousmalloc()
n octets en premier. Ensuite, vous avez besoin de plus de mémoire, de sorte que vousrealloc()
avec la taille n×f. Ensuite, vous avez besoin de plus de mémoire, si vous avez besoin n×f2 octets. Si vous voulezrealloc()
à utiliser l'espace de la précédente, deux blocs de mémoire, vous voulez vous assurer que n×f2 ≤ n + n×f. La résolution de cette équation, nous obtenons f≤ (sqrt(5)+1)/2 = 1.618 (le Nombre d'or). J'utilise un facteur de1.5
la plupart du temps.OriginalL'auteur Alok Singhal
C'est un peu un bouton chaud sujet comme il y a essentiellement 2 écoles de pensée sur le sujet
Personnellement, je suis dans le camp n ° 2. Attendre pour les très spéciale types d'applications, OOM est fatale période. Vrai, parfaitement écrit le code peut gérer un OOM, mais bien peu de gens comprennent comment écrire un code qui est fort dans le visage de pas de mémoire. Encore moins la peine de le faire car elle n'est presque jamais la valeur de l'effort.
Je n'aime pas passer le code d'erreur d'arrêt pour la fonction d'appel pour OOM est parce que c'est l'équivalent de dire que l'appelant "j'ai échoué et il n'y a rien que vous pouvez faire à ce sujet". Au lieu de cela, je préfère crash rapide de sorte que le montant de vidage est aussi instructif que possible.
malloc()
etrealloc()
qui vient se ferme avec un message d'erreur sur défaillance de la mémoire, mais ils ne le font pas que pour les quelques applications avec la meilleure des solutions).certainement vrai et certains produits (SQL server par exemple) sont très bien. Toutefois, ces produits sont rares exception. Il nécessite une quantité incroyable de la discipline, de l'exécution et de la compréhension. Tellement que les gens sont rarement même essayer de faire les choses.
donc, vous êtes essentiellement à dire parce que la plupart des gens n'a pas de gestion d'erreur de droit, vous ne devriez même pas la peine de soin pour les erreurs et, au lieu de laisser l'application crash et brûler, éventuellement d'endommager les données de l'utilisateur? Le problème est que OOM qui se passe lors de l'exécution sur la machine de l'utilisateur. Vous n'avez aucun contrôle sur les tailles de mémoire dans ces machines et sur le HD de l'espace pour le fichier d'échange. Puis ajouter les fuites de mémoire pour elle... en Plus, il est assez facile à tester que votre application peut gérer. Utiliser un wrapper pour malloc/realloc hasard renvoie la valeur NULL.
ce que je veux dire c'est qu'à défaut d'vite que possible est la meilleure manière absolue pour obtenir une exploitables rapport de bug. Je traite avec beaucoup de Watson bugs dans ma position. Les chemins de Code qui ne sont pas rapide de produire des données de grande valeur et très généralement suite à un bug en cours de correction. Les chemins de Code qui tentent de gérer de telles situations OOM presque toujours 1) le faire de manière incorrecte ou 2) passer un code qui ne peut pas gérer la situation. Les deux crash et de produire de très unactionable bugs depuis le crash se produit très loin après le premier vrai problème.
OriginalL'auteur JaredPar
La première règle que vous devriez suivre lorsque l'on travaille avec
realloc
est de ne pas affecter la valeur de retour derealloc
le pointeur de même que vous avez transféré. Cetteest mauvais. Si
realloc
échoue, elle renvoie null le pointeur, mais il n'a pas désallouer la mémoire ancienne. Le code ci-dessus null votrem->data
tandis que l'ancien bloc de mémoire anciennement pointé parm->data
seront plus susceptibles de devenir une fuite de mémoire (si vous n'avez pas d'autres références).La valeur de retour de
realloc
doit être stocké dans un autre pointeur de la premièreEnsuite, vous pouvez vérifier la réussite ou l'échec et de modifier la valeur de
m->data
en cas de succèsOriginalL'auteur AnT
C'est votre problème! Voici quelques critères:
Vous avez demandé que la mémoire pour une raison. Si il n'est pas disponible, est-ce votre programme de travail du condamné ou peut-il continuer à faire des trucs? Si l'ancien, vous souhaitez mettre fin à votre programme avec un message d'erreur; sinon, vous pouvez afficher un message d'erreur en quelque sorte et aller sur.
Est-il une possibilité de commerce à temps pour l'espace? Pourriez-vous répondre n'importe quelle opération que vous avez tenté à l'aide d'un algorithme qui utilise moins de mémoire? Cela ressemble à beaucoup de travail, mais serait en effet la possibilité de continuer votre programme de l'opération, en dépit de ne pas avoir assez de mémoire initialement.
Serait-ce mal pour que votre programme puisse continuer accuse le coup sans ces données et pas assez de mémoire? Si oui, vous devriez mettre fin avec un message d'erreur. Il est beaucoup mieux pour tuer votre programme de aveuglément poursuivre le traitement des données incorrectes.
OriginalL'auteur Carl Smotricz
Savoir comment le framework gère un OOM. De nombreux seront tout simplement pas gérer un OOM. La plupart du temps d'un cadre ne fonctionnera pas correctement dans le pas-gratuit-RAM conditions, sauf si il est dit très clairement et sans ambiguïté de quelque part qu'elle le sera. Si le cadre ne sera pas gérer un OOM et est multithread (nombreux sont de nos jours), un OOM va être la fin du spectacle pour le processus dans beaucoup de cas. Même si elle n'est pas multithread, il peut toujours être proche de l'effondrement. Si vous quittez le processus ou le cadre ne peut être un point discutable; un prévisible immédiate de sortie peut être juste un peu mieux qu'un crash d'un demi-point au hasard dans un avenir proche.
Si vous êtes en utilisant un but spécial de la sous-pool de mémoire (c'est à dire pas votre habitude de malloc) pour un ensemble bien défini d'opérations qui ne sont limités dans l'utilisation de la mémoire par OOM (c'est à dire l'opération en cours est annulée ou interrompue proprement sur OOM pour la sous-pool de mémoire, pas l'ensemble du processus ou de la mémoire principale de la piscine), et que les sous-piscine n'est pas utilisée également par le cadre d'application, ou si votre cadre et l'ENSEMBLE du reste de l'application est conçue pour maintenir un véritable état et de la poursuite de l'exploitation dans le pas-gratuit-RAM conditions (rare mais pas inexistant en mode noyau et de certains types de systèmes de programmation), vous pourriez être en droit de retourner un code d'erreur plutôt que de se bloquer le processus.
Idéalement, la majeure partie des allocations de mémoire (ou même plus idéalement tous les allocations) pour un morceau de traitement devrait être alloué dès que possible dans le traitement, idéalement avant qu'il ne commence vraiment, pour minimiser les problèmes de perte de l'intégrité des données et/ou le montant de la restauration de codage requis en cas d'échec. Dans la pratique, beaucoup de temps, pour économiser les coûts de programmation et de temps sur les projets, afin de préserver l'intégrité des données des applications reposent sur des transactions de base de données et en demandant à l'utilisateur/personne de soutien pour détecter une interface graphique crash (ou crash du serveur) et redémarrez l'application lors de la sortie de la mémoire des erreurs se produisent, plutôt que d'être écrite pour y faire face et de restauration à toute et à tous des milliers de potentiel OOM situations de la meilleure manière possible. Ensuite, les efforts sont axés sur le fait d'essayer de limiter l'exposition de l'application de la surcharge des situations, qui peuvent inclure une validation supplémentaire et limite la taille des données et de connexions simultanées et des requêtes.
Même si vous vérifiez la quantité de mémoire est signalé comme disponible, souvent d'autres codes peuvent alloc ou de la mémoire libre comme vous le faites, la modification de la base de votre mémoire et, éventuellement, conduisant à OOM. Donc la vérification des disponible gratuit RAM avant d'alloc est souvent pas une solution fiable au problème de vous assurer que votre application fonctionne à l'intérieur de la mémoire vive disponible limites et maintient l'intégrité des données assez de temps pour satisfaire les utilisateurs.
La meilleure situation dans l'est de connaître la quantité de mémoire de votre application nécessite dans tous les cas possibles, y compris un cadre frais généraux, et de garder cette figure dans la quantité de RAM disponible pour votre application, mais les systèmes sont souvent si complexes, avec des dépendances externes de dicter la taille des données si la réalisation de ce qui peut être irréaliste.
Le test de l'acide de cours est de vous satisfaire les utilisateurs suffisamment par le biais de haut-heure, et rares de la corruption de données, de la perte ou les accidents. Dans certains cas, une application ayant un processus de moniteur pour le redémarrer, s'il plante, il est utile.
En ce qui concerne le realloc:
Vérifier la valeur de retour de realloc - de la mettre dans une variable temporaire. En charge uniquement si elle est NULLE si la nouvelle taille demandée est >0. Dans d'autres cas, le placer dans votre non-variable temporaire:
par exemple
MODIFIER
Changé "la plupart des cas" à "un grand nombre de cas" (1).
Je reconnais que vous avez dit à supposer que "quelque chose peut être fait" si la mémoire ne peut pas être attribué. Mais la gestion de la mémoire est un très global d'examen (!).
OriginalL'auteur martinr
Il y a aussi une autre erreur subtile qui peut venir de realloc. La fuite de mémoire provenant retourné pointeur NULL est plutôt bien connu (mais assez rare de tomber sur).
J'avais dans mon programme crash une fois dans un tout qui est venu à partir d'un realloc appel. J'ai eu une structure dynamique qui a ajusté sa taille automatiquement avec un realloc ressemblant à ceci:
L'erreur que j'ai faite a été de ne pas cocher pour le m->max == 0, qui a libéré la zone de mémoire. Et fait de mon m->pointeur de données d'une rassis.
Je sais c'est un peu hors-sujet, mais c'était le seul vrai problème que j'ai jamais eu avec realloc.
realloc()
est tenu de retournerNULL
dans le cas d'un appel avec 0 de longueur. Cela n'aurait pas déclenché le bug en premier lieu. Fascinant, parce que je me souviens très bien d'un bug, que happenned autour de 2004, sur un très vieux (déjà pour l'époque) Solaris machine.OriginalL'auteur Patrick Schlüter
J'ai rencontré le problème.La configuration est OS:win7(64);IDE:vs2013;Debug(Win32).
Quand mon realloc retourné null due à la mémoire.J'ai deux solutions:
1.Modifier les propriétés du projet, pour permettre aux GRANDES ADRESSES.
2.Changer ma solution de plate-forme Win32 pour x64.
OriginalL'auteur Yuan Wen