вторник, 23 декабря 2008 г.

uleak

Создал новый проект на googlecode, который назвал uleak.

Сперва хотел просто выложить куда нибудь исходничек. Но подумал, что из этого может получиться что-то путное, если еще немного поработать.

Почему такое странное название? С названиями у меня всегда проблема. С одной стороны длинное название труднее запоминать. А с другой стороны длинные названия обычно больше говорят о себе. Но всетаки предпочитаю краткость. uleak - это типа как umount... :)

Надо сказать что в данном виде код пока что мало пригоден к использованию. Требует настройки на цель тестирования, и не имеет никаких сборочных сценариев.

К тому же, я там всякой фигни наворотил насчет фильтрации функций. Вероятно их надо будет потереть все. Да и с блокировками тоже малость намудрил.

Да и не все мысли еще воплотились. Например, под linux наверняка можно использовать libUnwind, которая почему-то не работает под FreeBSD. Но под linux uleak пока не заработает. В линуксе его наверное можно будет использовать к уже скомпиленным проектам через LD_PRELOAD, но я никогда с этим не работал.

Если у кого-то есть в сопровождении проблемные проекты, можно попробовать погонять их с uleak. Это поможет сделать его более универсальным и полезным.

PS: Кроме того на сайте uleak я доработал классификацию проблем, с удовольствием выслушаю критику.

PPS: самый короткий пост?

21 коммент.:

Alex Ott комментирует...

а чем не устраивают существующие библиотеки для поиска утечек?

Андрей Валяев комментирует...

О, ко мне зашел сам Alex Ott!!! :)

Да что-то они мне ничем не помогают... :) valgrind даже hello malloc почему-то не ловит. :) Кроме того утечка - не самая страшная проблема. программы от нее если и падают, то не сразу.

А вот например использование блока после освобождения никто вроде не ловит. uleak ловит. Переполнение блоков тоже ловит.

Он еще очень сырой, но firefox с ним уже запускается.

А с другой стороны может это просто из желания все делать по своему? не знаю... :)

Alex Ott комментирует...

ну есть google performance tools, которые вполне себе отлавливаю утечки. а для отслеживания обращения к освобожденным блокам есть dmalloc и т.п. см - http://xtalk.msk.su/~ott/ru/writings/prog-checking/
но на uleak я тоже посмотрю - я как раз ловлю очередную утечку, правда она похоже в чужой библиотеке, которая нам поставляется в бинарном виде

Андрей Валяев комментирует...

dmalloc я не пробовал. На первый взгляд весьма наворочанно.

tcmalloc мне тоже ничем не помог. Я писал, что мое приложение статическое, работает в голой FreeBSD и с отладкой там туго.

PS: что-то у меня dmalloc не работает. :)

$ LD_PRELOAD="/usr/lib/libdmalloccxx.so" firefox
/bin/sh: symbol lookup error: /usr/lib/libdmalloccxx.so: undefined symbol: __gxx_personality_v0
$ LD_PRELOAD="/usr/lib/libdmalloc.so" firefox
Ошибка сегментирования
$

Че-то не уровень.

uleak конечно не умеет еще конфигуриться в рантайме, не придумал как это лучше сделать, наверное через окружение вполне возможно.

С протоколами (файлами всмысле) сложно. во FreeBSD malloc вызывается чуть ли не из ядра, чуть что не так - бесконечная рекурсия... сложно с ней.

В linux как то все проще устроено.

Alex Ott комментирует...

ну я dmalloc на фре не проверял, так что не скажу...
P.S. а то, что ваше приложение работает на голой фре - это я хорошо знаю :-)

Андрей Валяев комментирует...

Сталкивался с континентом по работе?

Alex Ott комментирует...

и сталкивался по работе у клиентов, да и blaze - мой хороший знакомый :-)

Андрей Валяев комментирует...

Как тесен мир... :)

Alex Ott комментирует...

ну российская ИБ тусовка достаточно маленькая :-) я все-таки долго в этой области в россии работал, да и сейчас общаюсь

coff комментирует...

Мама!!! :-D Как хорошо на MSVC... там crt debug heap и утечки, и выход за границы, и использование после освобождения ловит, и еще делает много чего полезного... ))) Дает дамп списка блоков после некоторого момента, если нужно определить, не оставляет ли какая-либо конкрентная функция утечек. Инфу о куче любую выдает. Позволяет добавлять хуки на операции с кучей. Разные типы блоков в куче, с возможностью вызова коллбэка для каждого клиентского блока.

Alex Ott комментирует...

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

Андрей Валяев комментирует...

2Alex Ott: Я вот тоже что-то не особо представляю как это дело можно точно отследить. :)

Так, теории всякие строю.

2coff: В том то и проблема, что от сырого дампа толку мало... как и от сырого лога. Чтобы извлечь из всего этого какую-то пользу - надо его как-то обработать. суть проблемы извлечь таксказать.

Я вообще не особо люблю просто логи. Ради отладки приложение должно выдавать концентрированную/отфильтрованную информацию, компьютер - он железный, ему не трудно поработать над этим. :)

coff комментирует...

Нет, не отладчик, а crt с поддержкой debug heap. Грубо говоря, те же malloc, но с дополнительной информацией по каждому блоку...плюс guard-области. Ставишь hook на операции с памятью и мониторишь из той же проги. Можно перечислить выделенные клиентские блоки (причем crt может использовать твою процедуру), собирай статистику, какую тебе надо.

coff комментирует...

Если интересует инфа, посмотри в MSDN по _CrtDumpMemoryLeaks/_CrtSetDumpClient, _CrtSetAllocHook, _CrtDoForAllClientObjects, _CrtMemCheckpoint/_CrtMemDumpAllObjectsSince, _CrtSetBreakAlloc, _CrtSetReportMode/_CrtSetReportFile, и т.д.

coff комментирует...

И заметь, я не говорю, что "не нужно делать, уже все есть". Наоборот, я был бы только рад нормальному фришному менеджеру кучи. Сам бы рад написать, но пока руки не доходят.

morbo комментирует...

Разработчику Unix однажды задали вопрос: "Что бы вы переделали в Unix, если бы сейчас начали делать его снова?" Он ответил: "Я бы написал системный вызов creat с буквой e в конце названия."

Это к тому, что экономия на буквах не всегда оправдана в эстетическом плане и umount, на мой взгляд, тоже следовало бы назвать хотя бы unmount. Может быть и unleak звучало бы лучше?

Андрей Валяев комментирует...

2coff: Как менеджер кучи uleak будет плох... он медленный.

2morbo: Да в принципе название то не главное... но просто хочется чтобы оно было сколько нибудь благозвучно, и запоминаемо.

В принципе если в названии есть какая-то неправильность - оно запоминается лучше. :)

coff комментирует...

Андрей, на мой взгляд, корректное именование - один из главнейших поинтов в программировании. Как-то слышал выражение - "программирование - это умение давать имена сущностям"... или что-то вроде этого ))

2 Morbo
Да, для него главной проблемой было отсутствие буквы e в конце creat, а не отсутствие нормальных примитивов синхронизации и асинхронного ввода-вывода :-D

Из подобного могу вспомнить еще высказывание Линуса "message passing as the fundamental operation of the OS is just an excercise in computer science masturbation"... чувак просто не знал, что "QNX is a message-passing operating system".

Glider комментирует...

>>valgrind даже hello malloc почему-то не ловит

Поясните, пожалуйста, что такое есть hello malloc?

Андрей Валяев комментирует...

2Glider: Ну это я так образно выразился... предполагая программу следующего вида:

main() {
    malloc(100);
}

Glider комментирует...

2 Андрей Валяев:

ну тогда это не совсем верно. Даже в нормальном режиме valgrind сообщает об этой утечке в LEAK SUMMARY, а если запускать его с --leak-check=full, то он напишет и точное местоположение:

$ cat hello-malloc.c
#include <stdlib.h>

int main() {
malloc(100);
return 0;
}
$ gcc hello-malloc.c -o hello-malloc
$ valgrind --leak-check=full ./hello-malloc
==31547== Memcheck, a memory error detector
==31547== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
...
==31547==
==31547== HEAP SUMMARY:
==31547== in use at exit: 100 bytes in 1 blocks
==31547== total heap usage: 1 allocs, 0 frees, 100 bytes allocated
==31547==
==31547== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31547== at 0x4C246F5: malloc /tmp/vg/coregrind/m_replacemalloc/vg_replace_malloc.c:195
==31547== by 0x4004A5: main in /home/glider/hello-malloc
==31547==
==31547== LEAK SUMMARY:
==31547== definitely lost: 100 bytes in 1 blocks
==31547== indirectly lost: 0 bytes in 0 blocks
==31547== possibly lost: 0 bytes in 0 blocks
==31547== still reachable: 0 bytes in 0 blocks
==31547== suppressed: 0 bytes in 0 blocks
==31547==
==31547== For counts of detected and suppressed errors, rerun with: -v
==31547== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Другое дело, что это медленнее, чем подменять библиотечные функции, но зато довольно-таки надежно.