Отслеживание повреждения памяти на производственном Linux-сервере
Ребята, не могли бы вы рекомендовать инструмент для обнаружения повреждения памяти на многопоточном сервере, построенном на С++, и работающем под Linux x86_64? В настоящее время у меня возникает следующая проблема: каждые несколько часов мой сервер выходит из строя с помощью segfault, а дамп ядра показывает, что ошибка происходит в malloc/calloc, что определенно является признаком повреждения памяти где-то.
На самом деле я уже пробовал некоторые инструменты без большой удачи. Вот мой опыт:
-
Valgrind - отличный инструмент (я бы даже сказал лучше), но он слишком замедляет работу сервера, что делает его непригодным для производства. Я попробовал это на сценическом сервере, и это действительно помогло мне найти некоторые проблемы, связанные с памятью, но даже после их исправления я все равно получаю сбои на рабочем сервере. Я запускал свой сценический сервер под Valgrind в течение нескольких часов, но до сих пор не мог обнаружить серьезных ошибок.
-
ElectricFence считается настоящим болотом памяти, но я даже не мог его нормально работать. Он практически сразу же исчезает на сцене в случайных странных местах, где Valgrind вообще не обнаруживает никаких проблем. Может быть, ElectricFence не поддерживает многопоточность?.. Я понятия не имею.
-
DUMA - такая же история, как ElectricFence, но еще хуже. В то время как EF создавал дампы ядра с удобочитаемыми обратными трассами, DUMA показывает мне только "?????" (и да сервер построен с флагом -g).
-
dmalloc - я настроил сервер, чтобы использовать его вместо стандартных подпрограмм malloc, однако он зависает через несколько минут. Прикрепление gdb к процессу показывает, что он висел где-то в dmalloc: (
Я постепенно схожу с ума и просто не знаю, что делать дальше. У меня есть следующие инструменты для проверки: mtrace, mpatrol, но, возможно, у кого-то есть лучшая идея?
Я бы очень признателен за любую помощь по этой проблеме.
Обновление: Мне удалось найти источник ошибки. Однако я нашел его на сцене сервера, а не на производстве, используя helgrind/DRD/tsan - между несколькими потоками произошел datarace, что привело к повреждению памяти. Ключ должен был использовать правильные подавления valgrind, поскольку эти инструменты отображали слишком много ложных срабатываний. Тем не менее, я действительно не знаю, как это можно обнаружить на производственном сервере без каких-либо значительных замедлений...
Ответы
Ответ 1
Люди, мне удалось найти источник ошибки. Однако я нашел его на сервере сцены, используя helgrind/DRD/tsan - между несколькими потоками произошел datarace, что привело к повреждению памяти. Ключ должен был использовать правильные подавления valgrind, поскольку эти инструменты отображали слишком много ложных срабатываний. Тем не менее, я действительно не знаю, как это можно обнаружить на производственном сервере без каких-либо значительных замедлений...
Ответ 2
Да, проблемы с повреждением памяти C/С++ сложны.
Я также использовал несколько раз valgrind, иногда он выявлял проблему, а иногда и нет.
При исследовании результата valgrind не следует слишком быстро игнорировать его результат. Иногда после значительного времени, проведенного, вы увидите, что valgrind дал вам ключ к первому месту, но вы проигнорировали его.
Другой совет - сравнить изменения кода с ранее известным стабильным выпуском. Это не проблема, если вы используете какую-то систему управления версиями (например, svn). Изучите все связанные с памятью функции (например, memcpy, memset, sprintf, new, delete/delete []).
Ответ 3
Скомпилируйте свою программу с помощью gcc 4.1 и переключателя -fstack-protector-all. Если повреждение памяти вызвано разбитием стека, это должно быть способно ее обнаружить. Возможно, вам придется играть с некоторыми дополнительными параметрами SSP.
Ответ 4
Вы пробовали -fmudflap? (прокрутите несколько строк, чтобы увидеть доступные варианты).
Ответ 5
вы можете попробовать IBM очистить, но я боюсь, что это не openource..
Ответ 6
Google Perftools ---, который является открытым исходным кодом, может быть полезен, см. документацию
Ответ 7
Попробуйте следующее:
http://www.hexco.de/rmdebug/
Я использовал его экстенсивно, он имеет низкое влияние на производительность (в основном это влияет на количество RAM), но алгоритм распределения одинаков. Его всегда достаточно доказано, чтобы найти ошибки распределения. Ваша программа выйдет из строя, как только появится ошибка, и у нее будет подробный журнал.
Ответ 8
Я не уверен, поймал бы ваш конкретный баг, но переменная среды MALLOC_CHECK_
(malloc
man page) включает дополнительную проверку в реализации Linux по умолчанию malloc
по умолчанию и обычно не имеет значительных затрат времени исполнения.