Проблема с free () на структурах в C. Это не уменьшает использование памяти - PullRequest
8 голосов
/ 15 мая 2011

У меня проблема с free () для структуры в моей C-программе. Когда я смотрю на / proc // statm до и после освобождения, кажется, что он не уменьшается. Я использую free () неправильно в этом случае, или я читаю / proc // statm неправильно?

Вот тестовый пример, который приводит к проблеме:

struct mystruct {
    unsigned int arr[10000];
};

void mem() {
    char buf[30];
    snprintf(buf, 30, "/proc/%u/statm", (unsigned)getpid());
    FILE* pf = fopen(buf, "r");
    if (pf) {
        unsigned size; //       total program size
        unsigned resident;//   resident set size
        unsigned share;//      shared pages
        unsigned text;//       text (code)
        unsigned lib;//        library
        unsigned data;//       data/stack
        unsigned dt;//         dirty pages (unused in Linux 2.6)
        fscanf(pf, "%u %u %u %u %u %u", &size, &resident, &share, &text, &lib,         &data);
        printf("Memory usage: Data = %d\n", data*sysconf(_SC_PAGESIZE));
    }
    fclose(pf);
}

int main(int argc, char **argv) {
    mem();
    struct mystruct *foo = (struct mystruct *)malloc(sizeof(struct mystruct));
    mem();
    free(foo);
    mem();
}

Вывод:

Memory usage: Data = 278528
Memory usage: Data = 282624
Memory usage: Data = 282624

Когда я ожидаю, что это будет:

Memory usage: Data = 278528
Memory usage: Data = 282624
Memory usage: Data = 278528

Я провел аналогичный тест с malloc'ом (char *), затем освободил его, и он отлично работает. Есть что-то особенное в структурах?

Ответы [ 4 ]

12 голосов
/ 15 мая 2011

Ваш ответ - прямо здесь, при переполнении стека , но короткая версия такова, что по очень веским причинам распределитель памяти не возвращает память операционной системе хоста, а сохраняет ее (внутренне в вашей программе. пространство данных) как свободный список какой-то.

Некоторые из причин, по которым библиотека хранит память:

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

В основном по соображениям производительности выделенная память кучи не будет возвращена ОС после освобождения.Хотя он будет помечен как свободный, и, возможно, позже ядро ​​получит его обратно, или ваша программа выделит его и снова использует.

Я не знаю, что вы использовали для выделения / освобождения вашего (char *) .Разница, которую вы видели, может заключаться в том, что ваш (char *) был размещен в стеке, и процесс освобождения / освобождения его отличается от обработки в куче (управление памятью стека намного проще).

1 голос
/ 15 мая 2011

Всякий раз, когда free фактически освобождает память, зависит от реализации. Так что, возможно, free не возвращает память сразу, когда это большой кусок памяти. Я не думаю, что это имеет какое-либо отношение к struct с.

0 голосов
/ 15 мая 2011

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

...