yads
написал 27 мая 2008 года в 17:12 (976 просмотров)
Ведет себя
неопределенно; открыл 6 тем в форуме, оставил 36 комментариев на сайте.
На Си написано приложение регулярно использующее malloс, realloc и free. По ходу работы размер приложения в памяти постоянно растет, как будто malloс и realloc работают нормально, а free только когда захочет. Почему так происходит и надо ли что-то с этим делать?
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
Надо, запустить его под valgrind и устранить утечки памяти, если они есть.
Запустил, получил много ругательств на все используемые библиотеки, но после этого выполнение прекратилось, а потерь памяти обнаружено не было. Valgrind умеет обращаться с демонами? (память теряется во время работы, а не при запуске)
valgrind умеет с любыми программами работать. С какими параметрами запускал? «Definitely lost» есть?
# valgrind --leak-check=full --leak-resolution=high --undef-value-errors=yes --show-reachable=yes
……..
==1666== LEAK SUMMARY:
==1666== definitely lost: 0 bytes in 0 blocks.
==1666== possibly lost: 0 bytes in 0 blocks.
==1666== still reachable: 24,896 bytes in 8 blocks.
==1666== suppressed: 0 bytes in 0 blocks.
Хороший результат. Давай тогда к 1-му посту, как мерил? И что подразумевается под постоянно растет?
Смотрю поля VSZ,RSS в выдаче ps aux. Их значения увеличиваются.
Это еще не говорит о утечках. Утечки если они увеличиваются бесконечно.
Ну бесконечно не получится — когда-то произойдет перезагрузка и все начнется с начала, но за 2 дня работы выросло с 30Mb до 300Mb и продолжает также расти дальше.
А вот это уже симптом… Попробуй собрать с каким-нибудь ElectricFence ещё и посмотри, что получится.
Попробовал — не ругается, а память съедается и не отдается. Причем если при последующем malloc захватывается меньше (или столько же) чем в предыдущий то размер не растет, если больше то растет. (возможно эта память резервуруется за приложением, но отдавать приложению навсегда память которая им использована на 0.01 секунды, как-то не очень правильно).
На самом деле ни один (кроме OpenBSD’шного) free не отдаёт память назад ядру. Он её повторно использует в следующих malloc’ах. Т.е. такое, если ты запрашиваешь n, отдаёшь n (память просто помечается как свободная, но ядру не отдаётся), а потом запрашиваешь n+1, то уже запрошенной памяти не хватит, и malloc попросит у ядра ещё.
Чтобы запросов не было много, обычно используется такой алгоритм: каждый раз, когда требуется память запрашивается столько, сколько уже запрошено или, если нужно, больше. Т.е.
1. Выделено 0, запрашивается 100 => 100
2. Выделено 100, запрашивается 10 => 200
3. Выделено 200, запрашивается 1000 => 1200
4. Выделено 1200, запрашивается 10 => 2400
Возможно при каком-то хитром стечении обстоятельств эта схема может работать плохо. Но скорее всего — баг в malloc/free. Под чем запускаешь свою прогу?
Да, такой алгоритм выделения памяти в моем случаю должен приводить к наблюдаемым последствиям.
Сервер работает под Debian-linux, ядро 2.6.18.
Для больших кусков памяти используется mmap, так что такого эффекта быть не должно. Точнее, он не должен быть значительным.
Если ты постоянно запрашиваешь больше, чем отдаёшь, то память будет рости — это понятно. Проблема в том, что при хитрых запросах, память будет рости непропорционально запросам.
Данное приложение получает через внутренний сокет запрос, для его обработки захватывает несколько кусков памяти (их размер определяется из условий запроса), обрабатывает запрос, возвращает ответ через сокет, освобождает все куски памяти захваченные для обработки и засыпает до следующего запроса.
Т.е. большую часть времени память оно не использует и все что захватывает на время работы максимально быстро освобождает, но его размер в памяти растет.
Видимо всё-таки баг в glibc… Хотя это ооочень маловероятно. А попробуй собрать с, например, jemalloc.
C jemalloc не разобрался, но пока искал ее нашел функцию alloca. Проверил — похоже с ней размер приложения не растет. Только не понял получу ли я какие-то другие проблемы при использовании alloca вместо malloc или нет.
Прблемы есть — память быстро кончается…
Проблема решена. Надо использовать malloc, а после free вызывать malloc_trim и освобожденная память будет возвращена ядру.
Ваше решение не верно. Посмотрите на http://www.linuxdevcenter.com/lpt/a/6808
Мои знания английского недостаточны чтобы из такой статьи понять в чем я ошибся.
Не ли информации на русском?
alloca выделяет память на стеке. Стек, понятное дело, резиновый, но не настолько чтобы уж совсем.
У меня нет никаких негативных эффектов.
Не понял какие негативные эффекты проверялись?
Как ты описываешь, постоянный рост VM.