2016-09-27 3 views
0

Dans mon programme C, en fonction de l'entrée de l'utilisateur, la mémoire sera allouée pour une simulation donnée. Le problème initial auquel je suis confronté est que l'utilisateur peut demander un grand nombre à allouer, mais malloc() n'échoue jamais jusqu'à ce qu'il manque de mémoire, puis le programme se bloque. J'ai étudié la logique derrière cela et il me semble logique, voir [1] []. Une solution de contournement possible donnée ici "SIGKILL while allocating memory in C++" suggère de définir overcommit_memory dans /proc/sys/vm/overcommit_memory de 0 à 2.Comment vérifier si malloc() excède la mémoire

Cela a résolu le problème d'un côté. Mais puisque j'utilise -fsanitize=address j'obtiens l'erreur du désinfectant.

Y a-t-il une meilleure solution à cela?

+2

Si l'utilisateur donne la valeur 'X' comme entrée, vous savez * * combien d'octets qui se traduira par votre allocation de programme. Vous pouvez facilement limiter la valeur de 'X' à quelque chose qui n'épuise pas le système. Donc, si l'utilisateur entre une valeur trop grande, dites simplement à l'utilisateur qu'il est trop grand et demandez de nouveau la valeur. –

+1

En outre, vous * savez * que ['malloc'] (http://en.cppreference.com/w/c/memory/malloc) renvoie' NULL' s'il ne parvient pas à allouer de la mémoire? Vous pouvez également facilement vérifier cela et ne pas tenter de déréférencer le pointeur nul. –

+0

Veuillez fournir un exemple minimal, complet et vérifiable (http://stackoverflow.com/help/mcve) – stenliis

Répondre

0

Je suppose que le clang AddressSanitizer échoue parce qu'il y a une fuite légitime. Donc, ma réponse ne tient pas compte que:

Alternatives:

  1. Désactiver le comportement de surdimensionnement, comme vous l'avez déjà compris: cela va affecter d'autres processus et nécessite racine. Exécutez votre application dans une image de docker avec le tueur d'oom désactivé: cela n'affecte pas les autres processus, mais nécessite un docker d'installation root (c'est ma solution préférée). Write after malloc: peut prendre beaucoup de temps pour allouer un gros morceau de mémoire et votre processus peut encore être tué en raison d'un autre processus en cours d'exécution, mais ne nécessite pas de racine. Utilisez ulimit -v pour limiter la quantité de mémoire en fonction de la machine: cela ne nécessite pas de racine, mais votre processus peut être tué de toute façon.

Code pour la troisième alternative (pour Linux):

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <signal.h> 
#include <setjmp.h> 

jmp_buf resume_malloc; 

void handle_malloc_error(int sig) 
{ 
    longjmp(resume_malloc, sig); 
} 

void *memalloc(size_t sz) { 
    void *p = 0; 
    int sig = setjmp(resume_malloc); 
    if (sig == 0) { 
     p = malloc(sz); 
     signal(SIGSEGV, &handle_malloc_error); 
     memset(p, 0, sz); 
    } else { 
     p = 0; 
    } 
    signal(SIGSEGV, SIG_DFL); 
    return p; 
} 

int main(int argc, char *argv[]) 
{ 
    size_t sz = 160L * 1024 * 1024 * 1024L; 
    void *p; 
    for (int i=0; i < 100; i++) { 
     printf("size: %lu\n", sz); 
     p = memalloc(sz); 
     if (p == 0) { 
     printf("out of memory\n"); 
     break; 
     } 
     sz *= 2; 
    } 
} 
+0

Merci pour la bonne explication! J'ai vraiment aimé la solution en utilisant le saut en longueur. J'ai essayé cela, mais je suis toujours confronté au même problème. Donc, le processus est tué. À propos du désinfectant: Il n'y a pas de fuite. J'aurais dû mieux l'expliquer. Le désinfectant ne peut pas «s'initialiser» et juste après avoir exécuté le programme, «ReserveShadowMemoryRange a échoué en essayant de mapper 0xdfff0001000 octets, peut-être que vous utilisez ulimit -v». Les options root ne sont pas applicables dans mon cas car le code sera utilisé sur d'autres ordinateurs. J'apprécierais toutes les autres suggestions. – omid

+0

Encore une remarque que l'adresse sanitize fonctionne bien quand overcommit_memory est 0 – omid

+0

Il semble donc que d'autres processus essaient d'écrire dans une mémoire qui n'est pas réellement disponible et que votre processus est sélectionné par le tueur OOM pour être tué. Si c'est le cas, vous avez besoin de la première ou de la deuxième solution. – olivecoder