Gérez-vous les conditions de mémoire insuffisante?

9

Que faites-vous lorsque mallocretourne 0 ou une nouvelle exception de lancers? Arrêter ou essayer de survivre à la condition de MOO / enregistrer le travail de l'utilisateur?

mbq
la source
4
Lié sur Stackoverflow stackoverflow.com/questions/763159/…
ysolik
11
Argh. Je continue à lire ceci comme "hors du mana". Trop de jeux vidéo dans mon passé, je pense. :)
Adam Lear

Réponses:

4

J'éviterais le MOO comme éviter un crash.

Évitez de faire un gros morceau de travail (et allouez un gros morceau de mémoire) à la fois. Conservez les données sur le disque, faites confiance au cache de disque du système d'exploitation et utilisez autant que possible les E / S mappées en mémoire, et n'utilisez qu'une petite partie des données à la fois. Si de grandes quantités de données doivent être en ligne (servies avec une faible latence), gardez-les en mémoire sur plusieurs machines, comme le font toutes les grandes sociétés de moteurs de recherche. Ou achetez un SSD.

rwong
la source
Apparemment, cela a le plus de sens.
mbq
2
Il y a eu un grand débat sur la façon de gérer OOM avec élégance (RAII, sécurité d'exception, blah ...) mais une fois que j'ai réalisé que dans un système multithread avec plusieurs modules dynamiques (certains de tiers), même si votre thread ne l'a pas fait crash, il y a un moment malheureux où chaque thread verra un MOO. Si même un seul a décidé d'aller de l'avant, vous ne pouvez rien faire d'autre que des témoins oculaires.
rwong
13

La plupart des personnes qui répondent à cette question n'ont probablement jamais travaillé sur des systèmes embarqués, où malloc renvoyant 0 est une possibilité très réelle. Sur un système sur lequel je travaille actuellement, il y a un total de 4,25 K octets de RAM (soit 4352 octets). J'alloue 64 octets pour la pile et j'ai actuellement un tas de 1600 octets. Pas plus tard qu'hier, je déboguais une routine de marche en tas pour pouvoir suivre l'allocation et la libération de mémoire. La marche en tas utilise un petit tampon (30 octets) alloué statiquement pour sortir sur un port série. Il sera désactivé pour la version finale.

Comme il s'agit d'un produit de consommation, il vaut mieux ne pas manquer de mémoire une fois le produit sorti. Je suis sûr que ce sera le cas pendant le développement. Dans tous les cas, tout ce que je peux faire est de biper le haut-parleur plusieurs fois et de forcer un redémarrage.

tcrosley
la source
2
Installer des fonctionnalités à l'intérieur d'un petit espace est incroyable ... c'est une forme d'art comme le bonsaï
rwong
6
De nombreux projets sur les systèmes embarqués interdisent simplement l'allocation dynamique de mémoire. Le seul cas de MOO reste le débordement de pile.
mouviciel
Vous avez raison, mais surtout avec votre première phrase: la plupart de cela n'est tout simplement pas pertinent pour la plupart des développeurs, heureusement.
Konrad Rudolph
4

Pour être honnête, dans tous les projets que j'ai réalisés (gardez à l'esprit que je ne travaille encore nulle part), je n'ai jamais pensé que cela pourrait arriver, et donc je suppose que mes programmes mourraient très rapidement.

En outre, la gestion d'un MOO nécessite que vous ayez préalloué les ressources pour afficher le message d'erreur ou pour tout enregistrer, ce qui peut être assez gênant.

Je pense que ces jours-ci, la mémoire coûte moins cher que les arachides, ce n'est pas quelque chose qui devrait se produire fréquemment. À l'aube de la mémoire protégée et avant, c'était peut-être une préoccupation, mais maintenant? Les seules erreurs de MOO que j'ai jamais vues proviennent du code buggé.

zneak
la source
Je peux penser à récupérer une partie de la mémoire que le processus possède déjà et essayer de survivre et de récupérer (difficile si vous avez vidé quelque chose d'utile) ou de survivre en tant que données + restes qui tentent de le sauvegarder.
mbq
2

La vérification des codes de retour malloc est généralement inutile de toute façon.

Les systèmes d'exploitation modernes surchargent la mémoire: ils donnent aux processus plus de mémoire que ce qui est réellement disponible. La mémoire accordée à votre processus est virtuelle, le tout mappé sur une seule page mise à zéro.

Ce n'est que lorsque vous écrivez dans la mémoire qu'une page physique unique est allouée à vos processus. Si cette allocation échoue, le noyau terminera un processus (peut-être le vôtre!) Pour tenter de trouver de la mémoire. À ce stade, vous ne pouvez plus rien faire.

Kristof Provost
la source
J'ai eu une idée de me lancer dans une boucle avec un long sommeil à l'intérieur - et éventuellement de récupérer si le processus survivait au tueur OOM. J'ai l'impression que les processus ont plutôt été interrompus à cause de sa tentative d'utiliser l'adresse 0, mais je n'ai pas fait de tests solides.
mbq
Vous n'avez rien à faire de spécial pour faire face au tueur OOM. Si votre processus l'a déclenché mais n'a pas été sélectionné, il ne le saura jamais. Tout fonctionnera comme s'il y avait suffisamment de mémoire. Si, en revanche, votre processus est sélectionné, il sera interrompu et vous ne pourrez rien y faire.
Kristof Provost,
Mais je peux essayer d'attendre que le MOO libère de la mémoire, puis réallouer et continuer. J'ai l'impression que malloc / new n'attend pas que cela se produise.
mbq
Non, tu ne peux pas. Votre allocation réussira toujours. Vous obtiendrez toute la mémoire virtuelle que vous souhaitez. Ce n'est que lorsque vous le touchez que la mémoire physique est allouée. Dès que vous touchez une page non allouée, votre processus est suspendu. Le noyau cherchera plus de mémoire, ce qui pourrait l'amener à tuer un processus pour plus de mémoire. Si cela réussit (et qu'il ne tue pas le vôtre!), La page sera allouée et votre processus reprendra. Il n'y a aucun moyen pour votre processus de dire que cela s'est produit.
Kristof Provost
2
Je suis presque sûr que Windows ne commet jamais trop. Il peut valider plus que la RAM, mais pas plus que RAM + fichier d'échange.
CodesInChaos
2

À moins que vous ne développiez pour des systèmes embarqués, des systèmes en temps réel ou des systèmes qui sont si critiques que les pannes peuvent coûter des vies, ou des milliards de dollars ... Alors cela ne vaut probablement pas la peine financièrement de s'inquiéter des conditions de mémoire insuffisante.

Dans la plupart des cas, il y a peu de choses à faire lorsque vous manquez de mémoire de toute façon, car il n'y a pas de mémoire pour créer de nouveaux objets ou effectuer des tâches qui peuvent faire quelque chose. Vous devez peser le coût de l'application gérant le MOO par rapport aux avantages que vous en retirez.

Erik Funkenbusch
la source
Les systèmes en temps réel n'ont pas besoin de vérifier plus sur une panne de malloc que les autres systèmes.
zneak
@zneak - faux. Les systèmes en temps réel doivent être prévisibles et la mémoire insuffisante n'est pas prévisible, sauf si vous le planifiez spécifiquement.
Erik Funkenbusch du
Alors, qu'allez-vous faire de plus une fois que vous aurez frappé le MOO?
zneak
Mémoire libre, processus d'annulation, etc. Un système en temps réel n'a généralement pas de mémoire virtuelle ni de système d'échange car il doit être déterministe. Ainsi, il peut beaucoup plus facilement manquer de mémoire.
Erik Funkenbusch
Étant donné un certain chemin de code qui conduira inévitablement à une erreur OOM, je ne vois pas comment le plantage est une approche moins déterministe que la libération de mémoire et l'annulation de processus.
zneak
1

Je vérifierais toujours les erreurs. Si quelque chose renvoie une condition d'erreur, elle doit être gérée par votre programme. Même si c'est un message qui dit "Mémoire insuffisante, je dois y aller!", C'est mieux que "Violation d'accès", "vidage de mémoire" ou autre. L'une est une condition d'erreur que vous gérez, l'autre est un bogue. Et l'utilisateur le percevra également comme tel.

Pour votre cas spécifique, vous pouvez essayer d'annuler l'opération, libérer les ressources que vous avez allouées jusqu'à atteindre le point d'échec, signaler l'erreur et poursuivre l'exécution (peut-être lorsque vous essayez de quitter l'application, vous pouvez donner la option pour quitter immédiatement). De cette façon, l'utilisateur peut décider quoi faire, ou essayer de libérer de la mémoire en tripotant, en fermant des fichiers, etc. Bien sûr, la façon dont vous pouvez gérer la situation dépend fortement de votre programme - un programme qui n'est pas censé be interactive a probablement juste besoin de consigner l'erreur et soit de quitter, soit de continuer.

Dysaster
la source