Вопрос

Пожалуйста, помогите :) ос :Линукс

Где в "sleep(1000);", в это время "top (отображение задач Linux)" написал мне 7,7 % использования памяти.валгринд :не обнаружена утечка памяти.

Я понимаю, написал правильно, и весь результат malloc равен NULL.Но почему за это время "сна" моя программа НЕ уменьшила объем памяти?Чего не хватает?

Извините за мой плохой английский, спасибо


~ # tmp_soft
For : Is it free??  no
Is it free??  yes
For 0 
For : Is it free??  no
Is it free??  yes
For 1 
END : Is it free??  yes
END 

~ #top
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                
23060 root      20   0  155m 153m  448 S    0  7.7   0:01.07 tmp_soft    

Полный источник :tmp_soft.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

struct cache_db_s
{
 int       table_update;
 struct    cache_db_s * p_next;
};

void free_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t;
 while (*cache_db != NULL)
 {
  cache_db_t = *cache_db;
  *cache_db = (*cache_db)->p_next;
  free(cache_db_t);
  cache_db_t = NULL;
 }
 printf("Is it free??  %s\n",*cache_db==NULL?"yes":"no");
}

void make_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t = NULL;
 int n = 10000000;

 for (int i=0; i = n; i++)
 {
  if ((cache_db_t=malloc(sizeof(struct cache_db_s)))==NULL) {
   printf("Error : malloc 1 -> cache_db_s (no free memory) \n");
   break;
  }
  memset(cache_db_t, 0, sizeof(struct cache_db_s));

  cache_db_t->table_update = 1; // tmp 

  cache_db_t->p_next = *cache_db;
  *cache_db = cache_db_t;
  cache_db_t = NULL;
 }
}

int main(int argc, char **argv)
{
 struct cache_db_s * cache_db = NULL;

 for (int ii=0; ii  2; ii++) {
  make_cache_db(&cache_db);
  printf("For : Is it free??  %s\n",cache_db==NULL?"yes":"no");
  free_cache_db(&cache_db);
  printf("For %d \n", ii);
 }

 printf("END : Is it free??  %s\n",cache_db==NULL?"yes":"no");
 printf("END \n");
 sleep(1000);
 return 0;
}
Это было полезно?

Решение

Если вы пытаетесь установить, имеет ли ваша программа утечку памяти, то top не правильный инструмент для задания (valrind).

top показывает использование памяти, как видно ОС.Даже если вы называете free, нет никакой гарантии, что освобожденная память вернулась в ОС.Как правило, это не так.Тем не менее, память становится «свободной» в том смысле, что ваш процесс может использовать его для последующих ассигнований.

редактировать Если ваш libc поддерживает его, вы можете попробовать экспериментировать с M_TRIM_THRESHOLD .Даже если вы будете следовать этому пути, это будет сложно (один используемый блок, сидя рядом с верхней частью кучи, предотвратит выпуску всю свободную память под его выпуском в ОС).

Другие советы

По уважительным причинам практически ни один распределитель памяти не возвращает блоки в ОС.


Память из вашей программы может быть удалена только единицами страниц, да и то вряд ли будет соблюдено.

calloc(3) и malloc(3) взаимодействуют с ядром для получения памяти, если это необходимо.Но очень, очень немногие реализации free(3) когда-либо возвращают память ядру.1, они просто добавляют его в список свободных блоков, с которым calloc() и malloc() позже проверят, чтобы повторно использовать освобожденные блоки.Для такого подхода к проектированию есть веские причины.

Даже если функция free() захочет вернуть память в систему, ей понадобится хотя бы одна непрерывная страница памяти, чтобы заставить ядро ​​фактически защитить регион, поэтому освобождение небольшого блока приведет к изменению защиты только в том случае, если оно было тот последний небольшой блок на странице.

Теория Операции

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


1.Тот факт, что очень немногие реализации free() пытаются вернуть память в систему, вовсе не связан с расслаблением разработчиков.

Взаимодействие с ядром происходит намного медленнее, чем простое выполнение библиотечного кода, и польза от этого будет небольшой.Большинство программ имеют постоянный или увеличивающийся объем памяти, поэтому время, потраченное на анализ кучи в поисках возвращаемой памяти, будет полностью потрачено впустую.Другие причины включают тот факт, что внутренняя фрагментация делает маловероятным существование блоков, выровненных по страницам, и вполне вероятно, что возврат блока приведет к фрагментации блоков в обе стороны.Наконец, те немногие программы, которые возвращают большие объемы памяти, скорее всего, будут обходить malloc() и все равно просто выделять и освобождать страницы.

Вообще бесплатный () не возвращает физическую память в ОС, они все еще отображаются в виртуальной памяти вашего процесса.Если вы выделите большой кусок памяти, LIBC может выделить его MMAP ();Тогда, если вы освободите его, Libc может выпустить память в ОС MUNMAP (), в этом случае топ покажет, что использование вашей памяти снижается.

Итак, если вы хотите выпускать память в ОС явно, вы можете использовать MMAP () / MUNMAP ().

Когда ты free() памяти, она возвращается в пул памяти стандартной библиотеки C, а не возвращается в операционную систему.В видении операционной системы, как вы видите ее насквозь top, процесс все еще «использует» эту память.Внутри процесса библиотека C учла память и может вернуть тот же указатель из malloc() в будущем.

Я объясню это еще немного, но с другим началом:

Во время ваших звонков в malloc, реализация стандартной библиотеки может определить, что процессу не хватает памяти, выделенной операционной системой.В это время библиотека выполнит системный вызов, чтобы передать процессу больше памяти от операционной системы (например, sbrk() или VirtualAlloc() системные вызовы в Unix или Windows соответственно).

После того, как библиотека запрашивает дополнительную память у операционной системы, она добавляет эту память в свою структуру памяти, доступной для возврата из malloc.Позже звонки в malloc будет использовать эту память, пока она не закончится.Затем библиотека запрашивает у операционной системы еще больше памяти.

Когда ты free памяти, библиотека обычно не возвращает память операционной системе.Есть много причин для этого.Одна из причин заключается в том, что автор библиотеки полагал, что вы позвоните malloc снова.Если ты не позвонишь malloc опять же, ваша программа, вероятно, скоро завершится.В любом случае, вернуть память операционной системе не так уж и выгодно.

Другая причина, по которой библиотека может не возвращать память операционной системе, заключается в том, что память операционной системы выделяется большими непрерывными диапазонами.Его можно вернуть только тогда, когда весь непрерывный диапазон больше не используется.Схема звонка malloc и free может не очистить весь диапазон использования.

Две проблемы:

  • В make_cache_db(), линия

    for (int i=0; i = n; i++)
    

    вероятно, следует прочитать

    for (int i=0; i<n; i++)
    

    В противном случае вы выделите только один cache_db_s узел.

  • То, как вы назначаете cache_db в make_cache_db() кажется, что-то глючит.Похоже, что ваше намерение состоит в том, чтобы вернуть указатель на первый элемент связанного списка;но потому что ты переназначаешь cache_db на каждой итерации цикла вы в конечном итоге будете возвращать указатель на последний элемент списка.

    Если позже вы освободите список с помощью free_cache_db(), это приведет к утечке памяти.Однако на данный момент эта проблема замаскирована ошибкой, описанной в предыдущем пункте, которая приводит к выделению списков только длиной 1.

Независимо от этих ошибок, точка зрения, высказанная aix, очень обоснованна:Библиотеке времени выполнения не обязательно возвращать все free()разделите память операционной системы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top