LINUX.ORG.RU

ужасная работа с памятью


0

0

Ситуация такая.

Программа кушает память, и скушивает её всё. Когда malloc пытается выделить ещё памяти, то программа жестоко убивается. Это разве нормально ?? Таким образом, вместо того, чтобы malloc вернул NULL, получаем Killed ? И куда это годится ?

Можно ли предотвратить ?


man mmap, и не задавай больше глупых фачных вопросов.

Узнать, есть ли свободная память во время malloc() ещё можно, и он тогда вернёт NULL, а вот во время первого обращения к выделенной памяти ты не узнаешь, свободна она или нет (и трапнешься).

anonymous
()

Сделай man malloc, в конце в разделе BUGS описано, как отключить
overcommit (# echo 2 > /proc/sys/vm/overcommit_memory). Тогда
не будет SIGKILL.

Но честно говоря до такого лучше не доводить. Это значит, что
виртуальная память исчерпана, наступает свопинг, трашинг и отсосинг :-)))

Лучше поставь сам ограничение памяти на сильножрущий процесс.
Не надо ждать, пока он сожрет всю память в системе.
Это можно сделать как извне (ulimit), так и из самой программы
(setrlimit). Когда программа попробует аллокировать больше, чем
разрешено malloc вернет NULL.

HTH

Onanim
()
Ответ на: комментарий от idle

2idle: нашёл пример

#include <sys/mman.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

const size_t PAGE_SIZE = 0x1000;
const size_t RESERVE_AMOUNT = 32*1024*1024;
const size_t COMMIT_AMOUNT  = 1024*1024;

typedef struct Region
{
   size_t uncommited;
   void *reserved_base;
   void *uncommited_base;
} Region;

void *reserve(size_t size)
{
   void *mem;

   assert(size % PAGE_SIZE == 0);

   printf("Reserving %d KB (%ld pages free)...\n", size / 1024, sysconf(_SC_AVPHYS_PAGES));
   fflush(stdout);

   mem = mmap(NULL,
              size,
              PROT_READ | PROT_WRITE | PROT_EXEC,
              MAP_PRIVATE | /*MAP_NORESERVE | */MAP_ANONYMOUS,
              -1, 
              0);

   assert(mem != NULL);

   return mem;
}

int commit(void *adr, size_t size)
{
   void *a;

   assert(size % PAGE_SIZE == 0);

   printf("Commiting %d KB at %p (%ld pages free)...\n", size / 1024, adr, sysconf(_SC_AVPHYS_PAGES));
   fflush(stdout);
    
   a = mmap (adr,
             size,
             PROT_READ | PROT_WRITE | PROT_EXEC,
             MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
             -1,
             0);

   assert ((a == MAP_FAILED) || (a == adr));

   return a != MAP_FAILED;
}

int main()
{
   Region *map = NULL;
   int pass_count = 0;
   
   for(;;)
   {
      printf("----- Pass %d -----\n", pass_count++);
      fflush(stdout);

      map = (Region *)malloc(sizeof(Region));

      if((map->reserved_base = reserve(RESERVE_AMOUNT)) == MAP_FAILED)
      {
         perror(NULL);
         exit(1);
      }

      map->uncommited_base = map->reserved_base;
      map->uncommited = RESERVE_AMOUNT;

      while(map->uncommited > 0)
      {
         if(!commit(map->uncommited_base, COMMIT_AMOUNT))
         {
            perror(NULL);
            exit(1);
         }

         map->uncommited -= COMMIT_AMOUNT;
         ((char*)map->uncommited_base) += COMMIT_AMOUNT;
      }
   }

   return 0;
}

----------------------------------

И что - программа завершает работу при 63-м пассе. т.к. когда уже
 скушали ~2 Gb памяти. А у меня всего 128+360 Mb. Как-то не стыкуется.

Keiko
() автор топика
Ответ на: комментарий от Keiko

не понимаю, что вас удивляет.

commit - это просто noop, в данном случае.
и почему она у вас так называется?

idle ★★★★★
()
Ответ на: комментарий от idle

это не у меня, этот пример из какого-то топика на аналогичную тематику. Вобщем суть проблемы:

- мне нужно выделить память
- узнать, была ли она _точно_ выделена.

malloc() как очевидно не спасает. mmap тоже. Как разрешить эту проблему я не понял :(

P.S. kernel-2.4.27

Keiko
() автор топика
Ответ на: комментарий от Keiko

> - мне нужно выделить память
> - узнать, была ли она _точно_ выделена.
>
> malloc() как очевидно не спасает
>

Блин, ты man malloc прочитал? Секцию BUGS?
Сделал 'echo 2 > /proc/sys/vm/overcommit_memory' (ессно как root)?
Что, и после этого у тебя malloc() не возвращает NULL?

Onanim
()
Ответ на: комментарий от Keiko

> теперь я хотел бы знать - это ЕДИНСТВЕННОЕ решение ?

Не знаю :-/ Решение чего? То, что malloc() не возвращает NULL при
включенном overcommit - AFAIK так и задумано было (насколько это
полезная и нужная фича - другой вопрос). Если не нравится такое
поведение malloc() - выключи этот overcommit нафиг (если у тебя
в дистрибутиве он по умолчанию включен). IMHO нет никакой проблемы.
Если ты делаешь программу для распространения и боишься, что
вдруг у пользователья включен overcommit - забей на это. Это
уже его, пользователя/админа дело, как чего у себя настраивать.
Может он фанатеет по overcommit'у, тебе-то что. Ну разве что
если у тебя программа действительно немеряно памяти жрет, то
напиши в документации - мол так и так, минздрав напоминает про
overcommit ;-)

HTH

Onanim
()
Ответ на: комментарий от Onanim

keiko@debian:tmp$ cat 26.c
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    char  *p;
    const int s = 20 * 1024 * 1024;

    while(1)
    {
        p = (char *)malloc(s);

        if(!p)
        {
            printf("NULL!\n");
            return 1;
        }

        printf("malloced\n");

        memset(p, 0, s);
    }

    return 0;
}
keiko@debian:tmp$ cat /proc/sys/vm/overcommit_memory
2
keiko@debian:tmp$ gcc -o 26 26.c
keiko@debian:tmp$ ./26
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
malloced
Killed
keiko@debian:tmp$ 

-----------------------------------

И что ? :(

echo 2 > /proc/sys/vm/overcommit_memory насколько я понял работает
только для 2.6 (в доке параметр "2" помечен как NEW).

Получается, что для 2.4 - сосать лапу ?

Keiko
() автор топика
Ответ на: комментарий от Keiko

> Получается, что для 2.4 - сосать лапу ?

Виноват. Посыпаю голову пеплом. Про 2.4 забыл :-( Вокруг одни 2.6

Про какое-то общепринятое решение для 2.4 не знаю, никогда не
требовалось. Может кто чего подскажет.

Onanim
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.