Les programmes de restauration de mémoire bloquent le système

3

J'ai le problème suivant: un programme a un bogue comme celui-ci

int main() {
  for(;;) {
    char *p = (char*)std::malloc(1024);
    std::memset(p, 1, 1024);
  }
}

Et cela continue à allouer de la mémoire jusqu'à ce que mon système commence à échanger des pages d'autres applications en faveur de ce programme et que je ne puisse plus rien faire dans la boîte. J'ai rencontré ce problème plusieurs fois avec différentes applications (aujourd'hui, c'était avec Moonlight 2 beta dans Firefox). Si le problème vient du fait que le programme provoque l’échange de la mémoire d’un autre programme et qu’il peut utiliser davantage de mémoire physique.

Naturellement, j’ai examiné ulimit et trouvé deux réglages:

-mla taille maximale de l'ensemble résident de
-vla taille de la mémoire virtuelle

J'ai lu que le premier indique la taille totale de la mémoire physique que le processus peut utiliser à la fois. Pour moi, il semble que cela soit plus raisonnable que la taille totale de la mémoire virtuelle, car elle peut être partagée, et cela pourrait n'avoir aucune importance, car elle est de toute façon remplacée. J'ai donc ajouté ce qui suit à mon article .bashrcaprès avoir examiné la taille habituelle des ensembles de résidents top, allant jusqu'à environ 120 Mo pour une session firefox habituelle, que j'ai trouvée.

# limit usage to 256MB physical memory out of 1GB
ulimit -m 262144

Mais après l' exécution de mon extrait de test ci - dessus, il reste Brough mon système vers le bas, et je dû attendre environ 5 minutes jusqu'à ce que le terminal a reconnu mes ^Ctouches. Habituellement, si je ne réagis pas dans les toutes premières secondes, dans ces situations, je ne peux que cliquer sur le bouton de réinitialisation, ce que je n'aime vraiment pas - quelqu'un a-t-il une stratégie pour résoudre ce problème? Pourquoi la limitation physique ne fonctionne-t-elle pas? Il me semble que de cette façon, les autres applications devraient toujours disposer de suffisamment de mémoire physique pour réagir de manière sensée.

Johannes Schaub - litb
la source

Réponses:

1

Avez-vous essayé avec le -vdrapeau?

L'ensemble de travail résident est défini par la quantité maximale de mémoire conservée en tant qu'ensemble de travail dans la RAM avant la permutation. Ainsi, la quantité totale de mémoire, y compris les parties échangées de l’ensemble de travail, ne sera pas limitée. Le -vdrapeau devrait faire le travail.

TAILLE DE MÉMOIRE VIRTUELLE: la plus utile des limitations liées à la mémoire, car elle inclut tous les types de mémoire, y compris la pile, le tas et les fichiers mappés en mémoire. Toute tentative d'allocation de mémoire excédant cette limite échouera avec une erreur d'insuffisance de mémoire.

Il est assez étonnant que les ressources du réseau décrivant cela en profondeur ne soient pas vraiment faciles à trouver! J'ai fait l'expérience sur ma boîte Linux.

Il s’arrête exceptionnellement avec

  ulimit -v 100000

et n'a pas avec le -mdrapeau. La seule chose qui m'a surpris est l'exception:

segmentation fault

J'aurais prévu out of memory.

Jdehaan
la source
3
malloc () ne lèvera pas une exception, mais retournera zéro. Ensuite, le code essaiera d’écrire là-bas ... donc sa faute de segmentation.
Liori
Cependant, je me demande pourquoi mon système reste bloqué même avec -m. Je pensais que si la mémoire physique est limitée pour le processus (son ensemble de travail), les autres applications ne seront pas remplacées et resteront réactives. Mais le système se verrouille quand même. Pourquoi est-ce? Si rien d’autre n’aide, j’utiliserai la mémoire virtuelle, même si cela inclut beaucoup de choses qui ne participent pas à la fermeture de la machine (fichiers mappés en mémoire, etc.).
Johannes Schaub - litb Le
@ liiori, bon point, idiot moi, je pense que je fais trop de C ++ ... :-)
jdehaan
@litb Je voulais dire qu'avec -mla quantité de mémoire physique utilisée, le virtual est limité. Donc, le processus va échanger. J'ai lu que tous les types de support Shell / Linux ne sont pas supportés -m. Vous pouvez vérifier ce qui est réellement défini avec ulimit -aou avec ulimit -m(sans paramètre)
jdehaan
1

Je pense que l’implémentation d’Ulimimit est aléatoire sur presque tous les systèmes d’exploitation. J'utilise ulimit -S -v sous Linux depuis six ans. Six! Et il semble que certains noyaux ne le supportent plus. J'ai un Mac et OS X 10.6 ne le supporte pas. J'ai aussi essayé avec -m. Dans mon ancien bureau avec Ubuntu 9.04, ulimit -S -v fonctionne bien.

En effet, je cherche une vraie solution à cela. Je ne peux tout simplement pas croire que les utilisateurs d’Apple, par exemple, permettent à leur programme de se déchaîner en mémoire.

hectorpal
la source
0

Fuite de mémoire classique. J'ai bien peur qu'il faille corriger l'application en question, le système d'exploitation ne peut pas faire grand chose. Tout ce que le système d'exploitation peut faire est de restreindre la mémoire d'une application, mais l'application en question plantait / segfault et entraînait peut-être le système d'exploitation ou au moins xorg avec elle.

Vous pouvez ld_preload une autre version de malloc et ajouter un thread pour le libérer après un nombre de secondes spécifié. Je doute que cela fonctionne, cependant ...

Vous auriez besoin de ce tut: http://lattice.umiacs.umd.edu/files/functions_tr.pdf

Dilemme
la source