Forum Linux.général pourquoi malloc peut échouer alors que linux utilise de la mémoire virtuelle

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
3
23
juil.
2019

bonjour,

voila tout est dans la question. On m'a toujours appris de vérifier si malloc() renvoyait un pointeur null ou non. Or je ne vois pas commment mon allocation mémoire peut échouer alors que linux utilise de la mémoire virtuelle. Donc même si je demande 20 GO de ram et que ma machine n'en possede que 4, malloc() ne me retournera pas un pointeur null.

Merci d'avance pour vos éclaircissements.

  • # /proc/sys/vm/overcommit_memory

    Posté par  (site web personnel) . Évalué à 5.

    Regarde le mécanisme d'overcommit, par exemple dans man 5 proc.

    Debian Consultant @ DEBAMAX

    • [^] # Re: /proc/sys/vm/overcommit_memory

      Posté par  . Évalué à 1.

      ca me dit juste que la limite est calculé par rapport à la formule dans /proc/sys/vm/overcommit_memory, or dans ce fichier je n'ai que le caractere 0.

      Il me dit également d'aller voir dans Documentation/vm/overcommit-accounting mais ce fichier n'existe pas :(

      je suis sur Ubuntu.

      • [^] # Re: /proc/sys/vm/overcommit_memory

        Posté par  (site web personnel) . Évalué à 1.

        Le fichier Documentation/vm/overcommit-accounting fait partie du package kernel-doc (centos/redhat/mageia …) ou linux-doc (debian/ubuntu …)

      • [^] # Re: /proc/sys/vm/overcommit_memory

        Posté par  (site web personnel) . Évalué à 3.

        Alors, j'ai assez bon espoir que la page de manuel dans Ubuntu soit assez similaire à ce que j'ai dans Debian, qui détaille ceci :

        /proc/sys/vm/overcommit_memory
            This file contains the kernel virtual memory accounting mode. Values are:
        
            0: heuristic overcommit (this is the default)
            1: always overcommit, never check
            2: always check, never overcommit
        
            In mode 0, calls of mmap(2) with MAP_NORESERVE are not checked, and the default check is very weak, leading to the risk of getting a process "OOM-killed".
            In mode 1, the kernel pretends there is always enough memory, until memory actually runs out. One use case for this mode is scientific computing applications that employ large sparse arrays. In Linux kernel versions before 2.6.0, any nonzero value implies mode 1.
            In mode 2 (available since Linux 2.6), the total virtual address space that can be allocated (CommitLimit in /proc/meminfo) is calculated as
            CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap
            where:
        
            total_RAM is the total amount of RAM on the system;
            total_huge_TLB is the amount of memory set aside for huge pages;
            overcommit_ratio is the value in /proc/sys/vm/overcommit_ratio; and
            total_swap is the amount of swap space.
        
            For example, on a system with 16GB of physical RAM, 16GB of swap, no space dedicated to huge pages, and an overcommit_ratio of 50, this formula yields a CommitLimit of 24GB.
            Since Linux 3.14, if the value in /proc/sys/vm/overcommit_kbytes is nonzero, then CommitLimit is instead calculated as:
            CommitLimit = overcommit_kbytes + total_swap
            See also the description of /proc/sys/vm/admiin_reserve_kbytes and /proc/sys/vm/user_reserve_kbytes. 
        

        Et la description des différents modes me semble bien expliquer ce que tu cherchais à comprendre, non ?

        (Pour la visualiser en ligne : https://manpages.debian.org/buster/manpages/proc.5.en.html)

        Debian Consultant @ DEBAMAX

    • [^] # Re: /proc/sys/vm/overcommit_memory

      Posté par  (site web personnel) . Évalué à 4.

      man 3 malloc

      NOTES
             By default, Linux follows an optimistic memory allocation strategy.  This means that when mal‐
             loc()  returns non-NULL there is no guarantee that the memory really is available.  In case it
             turns out that the system is out of memory, one or more processes will be killed  by  the  OOM
             killer.   For  more  information,  see  the  description of /proc/sys/vm/overcommit_memory and
             /proc/sys/vm/oom_adj in proc(5), and the Linux kernel source file Documentation/vm/overcommit-
             accounting.
      (...)
      
  • # malloc peut retourner un pointeur nul

    Posté par  . Évalué à 3.

    Donc même si je demande 20 GO de ram et que ma machine n'en possede que 4, malloc() ne me retournera pas un pointeur null.

    Chez moi si, ça retourne un pointeur nul, donc c'est possible :

    #include <stdlib.h>
    #include <stdio.h>
    
    int main()
    {
        size_t L = (size_t)20*1024*1024*1024;
        char *str = malloc(L);
        printf("str=%p\n", str);
    }

    Résultat d'exécution :

    str=(nil)
    
    • [^] # Re: malloc peut retourner un pointeur nul

      Posté par  (site web personnel) . Évalué à 10. Dernière modification le 23 juillet 2019 à 13:46.

      Oui il fait chaud, mais soyons joueur :

      #include <stdlib.h>
      #include <stdio.h>
      
      int main()
      {
          size_t L = (size_t)20*1024;
          char *str = malloc(L);
          printf("str=%p\n", str);
      }
      $ gcc maloq.c
      $ size ./a.out 
         text    data     bss     dec     hex filename
         1617     608       8    2233     8b9 ./a.out
      
      $ ulimit -a
      core file size          (blocks, -c) 0
      data seg size           (kbytes, -d) unlimited
      scheduling priority             (-e) 0
      file size               (blocks, -f) unlimited
      pending signals                 (-i) 63452
      max locked memory       (kbytes, -l) 16384
      max memory size         (kbytes, -m) unlimited
      open files                      (-n) 1024
      pipe size            (512 bytes, -p) 8
      POSIX message queues     (bytes, -q) 819200
      real-time priority              (-r) 0
      stack size              (kbytes, -s) 8192
      cpu time               (seconds, -t) unlimited
      max user processes              (-u) 63452
      virtual memory          (kbytes, -v) unlimited
      file locks                      (-x) unlimited
      
      $ ./a.out 
      str=0x5577f3ab2260
      # virtual memory
      $ sh -c 'ulimit -v 1000 ; ./a.out'
      Segmentation fault
      (...)
      $ sh -c 'ulimit -v 2359 ; ./a.out'
      Segmentation fault
      $ sh -c 'ulimit -v 2360 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: failed to map segment from shared object
      (...)
      $ sh -c 'ulimit -v 4491 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: failed to map segment from shared object
      $ sh -c 'ulimit -v 4492 ; ./a.out'
      str=(nil)
      (...)
      $ sh -c 'ulimit -v 4507 ; ./a.out'
      str=(nil)
      $ sh -c 'ulimit -v 4508 ; ./a.out'
      str=0x560591527260
      # stack size
      $ sh -c 'ulimit -s 11 ; ./a.out'
      Segmentation fault (core dumped)
      $ sh -c 'ulimit -s 12 ; ./a.out'
      str=0x55f97206f260
      # data seg size
      $ sh -c 'ulimit -d 19 ; ./a.out'
      Segmentation fault
      $ sh -c 'ulimit -d 20 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: cannot create shared object descriptor: Cannot allocate memory
      (..)
      $ sh -c 'ulimit -d 27 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: cannot create shared object descriptor: Cannot allocate memory
      $ sh -c 'ulimit -d 28 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: cannot map zero-fill pages
      (...)
      $ sh -c 'ulimit -d 51 ; ./a.out'
      ./a.out: error while loading shared libraries: libc.so.6: cannot map zero-fill pages
      $ sh -c 'ulimit -d 52 ; ./a.out'
      str=(nil)
      (...)
      $ sh -c 'ulimit -d 175 ; ./a.out'
      str=(nil)
      $ sh -c 'ulimit -d 176 ; ./a.out'
      str=0x55b201c5a260
      • [^] # Re: malloc peut retourner un pointeur nul

        Posté par  . Évalué à 2.

        Je ne comprend pas bien. Pourquoi est-ce que la taille de ton allocation (20 ko) n'a pas l'air de ressortir dans aucun de tes tests?

        Il faut compter la stdlib aussi?

        Quelles sont tes conclusions?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.