Использование памяти программы C - больше памяти сообщается, чем выделено - PullRequest
2 голосов
/ 24 августа 2011

У меня есть следующий код:

int main()
{
   char * str1 = (char*)malloc(101 * sizeof(char));
   for (int i=0; i<100; i++)
   {
      str1[i] = 'b';
   }
   str1[100] = 0;

   char * str2 = (char*)malloc(1001 * sizeof(char));
   for (int i=0; i<1000; i++)
   {
      str2[i] = 'a';
   }
   str2[1000] = 0;


   for (int i=0; i<7000; i++)
   {
      char * tmp = str2;
      str2 = (char*) malloc((strlen(str2) + strlen(str1) + 1) * sizeof(char));
      sprintf(str2, "%s%s", tmp, str1);
      free(tmp);
   }

   free(str1);
   free(str2);
}

При запуске диспетчер задач сообщает о следующем использовании памяти: начало программы - 1056K, конец программы - 17 748 КБ

Насколько мне известно, утечек памяти нет, и я скомпилировал их без символов отладки (режим выпуска).

Есть идеи, почему это может произойти?

Ответы [ 3 ]

10 голосов
/ 24 августа 2011

Я думаю, это потому, что free не нужно возвращать память в ОС.Он просто возвращает его в свободный пул, откуда он может быть выделен как malloc.

3 голосов
/ 24 августа 2011

Это, вероятно, артефакт того, как malloc выбирает из доступных пулов памяти для удовлетворения malloc.Кроме того, такие инструменты, как TaskManager и top (для unix), как известно, плохо показывают фактическую память, используемую процессом.Каждый раз, когда один из моих клиентов дает мне максимальный результат и говорит, что мой процесс протекает, я съеживаюсь, потому что теперь я должен доказать, что это не так.

1 голос
/ 24 августа 2011

malloc - это функция управления памятью, предоставляемая стандартной библиотекой C. Когда ваша программа вызывает malloc, она не выделяет память напрямую из операционной системы. Реализации Malloc обычно имеют пул памяти, который они разделяют на блоки для удовлетворения запросов на выделение. Когда вы звоните бесплатно, вы только отдаете свой блок памяти обратно в этот пул памяти.

Повторные вызовы malloc в конечном итоге выделяют всю память из пула памяти, управляемого стандартной библиотекой. На этом этапе необходимо выполнить системный вызов, чтобы получить больше памяти от операционной системы. В Linux это системный вызов brk, без сомнения, в Windows будет нечто подобное.

Диспетчер задач в Windows или top в Linux сообщит об объеме памяти, выделенной операционной системе для вашего процесса. Обычно это больше, чем объем памяти, выделенный вашей программе через malloc.

Если вы отслеживаете программу в linux, вы можете видеть, как выполняются эти вызовы malloc и brk

ltrace -S <some program>
malloc(65536 <unfinished ...>
SYS_brk(NULL)                = 0x2584000
SYS_brk(0x25b5000)           = 0x25b5000
SYS_brk(NULL)                = 0x25b5000
<... malloc resumed> )       = 0x2584010

В этом примере мы пытаемся выполнить malloc (65536), но системе malloc не хватает свободной памяти для удовлетворения этого запроса. Поэтому он вызывает системный вызов brk (), чтобы получить больше памяти от операционной системы. После завершения этого вызова он может возобновить вызов malloc и предоставить программе запрошенную память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...