LINUX.ORG.RU

О работе с valgrind

 , ,


0

0

Valgrind -- мощный инструмент программиста, позволяющий отыскивать ошибки работы с памятью. Каждый начинающий (и не только) разработчик на языке C просто обязан научиться пользоваться данным средством. В этом и поможет статья, которую можно прочитать, перейдя по ссылке.

>>> Статья

★★★★

Проверено: Shaman007 ()

> Каждый начинающий (и не только) разработчик на языке C просто
> обязан научиться пользоваться данным средством.

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

Zuljin
()

Не Valgrind надо изучать, а язык С более толково и думать головой, когда программы пишешь, тогда и ошибок не будет. А еще лучше Pascal/Ada...

anonymous
()
Ответ на: комментарий от anonymous

Не говорите за всех.
Когда вам предложат двойную зарплату за разработку на C/C++, вы не только их и valgrind изучите, но и пис_ть кипятком будете от счастья.

anonymous
()
Ответ на: комментарий от Zuljin

> Каждый программист обязан научиться работать с памятью, а не с подобными костылями.

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

а Вы, видать, либо про valgrind только слышали где-то краем уха, либо не писали на С ни чего сложнее "hello, world", либо вообще не знаете С/С++

vadiml ★★★★★
()
Ответ на: комментарий от anonymous

C - для богатых и счастливых, Pascal/Ada - для бедных, но ещё более счастливых.

Наверное так :)

anonymous
()
Ответ на: комментарий от anonymous

>Чем лучше? Добавляйте в таком случае IMHO... всегда.

А по-умолчанию любое высказывание и есть IMHO.

anonymous
()

как раз эту замечательную программу надо использовать для отладки достаточно больших проектов, вроде Firefox

Karbofos
()

Программа супер! Мне как начинающему программисту очень нужна!

anonymous
()

Хороший инструмент .
Я как то искал аналог для винды , не нашел , одни коммерческие , так что еще один гвоздь ...

kitov ★★★
()
Ответ на: комментарий от kitov

Эх, поздно он мне попался. А то приходилось костыли изобретать, malloc/free по #ifdef'у переопределял да в логи вызовы сбрасывал. А потом еще костыль - парсилка на перле логи разбирала. И то, утечки-то находились на ура, а вот за массив выползти - этого уже не отследишь.

Только сейчас уже не нужно :( Из любителей-недокодеров в профессиональные недоадмины перешел, только на перле да шелле и пишу.

silent
()
Ответ на: комментарий от kitov

>а где там утечки ?

вот, например, qt-4.3.2:

особенно печалят строки по завершению программы:
malloc/free: in use at exit: 564,992 bytes in 3,583 blocks.
malloc/free: 77,437 allocs, 73,854 frees, 17,448,426 bytes allocated.

утечки есть.

$ valgrind release/treesol
...skip
==28088== Invalid read of size 8
==28088==  Address 0x4064770 is 72 bytes inside a block of size 75 alloc'd
...skip
==28088==    by 0x76B6704: QIconvCodec::createIconv_t(char const*, char const*) (in /usr/lib64/qt4/libQtCore.so.4.3.2)
...skip
==28088== Invalid read of size 8
==28088==  Address 0x4064770 is 72 bytes inside a block of size 75 alloc'd
...skip
==28088==    by 0x76B6704: QIconvCodec::createIconv_t(char const*, char const*) (in /usr/lib64/qt4/libQtCore.so.4.3.2)
...skip
==28088== Syscall param writev(vector[...]) points to uninitialised byte(s)
...skip
==28088==    by 0x509D346: QPixmap::fromImage(QImage const&, QFlags<Qt::ImageConversionFlag>) (in /usr/lib64/qt4/libQtGui.so.4.3.2)
...skip
==28088==  Address 0x9E7BD19 is 553 bytes inside a block of size 16,384 alloc'd
...skip
==28088==    by 0x5052C6A: qt_init(QApplicationPrivate*, int, _XDisplay*, unsigned long, unsigned long) (in /usr/lib64/qt4/libQtGui.so.4.3.2)
...skip
==28088==
==28088== ERROR SUMMARY: 25 errors from 7 contexts (suppressed: 24 from 2)
==28088== malloc/free: in use at exit: 564,992 bytes in 3,583 blocks.
==28088== malloc/free: 77,437 allocs, 73,854 frees, 17,448,426 bytes allocated.
==28088== For counts of detected errors, rerun with: -v
==28088== searching for pointers to 3,583 not-freed blocks.
==28088== checked 9,227,760 bytes.
==28088==
==28088== LEAK SUMMARY:
==28088==    definitely lost: 3,148 bytes in 72 blocks.
==28088==      possibly lost: 304 bytes in 1 blocks.
==28088==    still reachable: 561,540 bytes in 3,510 blocks.
==28088==         suppressed: 0 bytes in 0 blocks.
==28088== Rerun with --leak-check=full to see details of leaked memory.

MaratIK
()
Ответ на: комментарий от anonymous

>Не Valgrind надо изучать, а язык С более толково и думать головой, когда программы пишешь, тогда и ошибок не будет. А еще лучше Pascal/Ada...

Только в теории. На практике же, как это обычно и бывает, все не так оптимистично. Программ без ошибок не бывает -- доказано временем.

Чем лучше Pascal/Ada?

Demon37 ★★★★
() автор топика
Ответ на: комментарий от silent

> Эх, поздно он мне попался. А то приходилось костыли изобретать, malloc/free по #ifdef'у переопределял да в логи вызовы сбрасывал.

Вообще-то как минимум glibc имеет встроенные средства для отладки выделения памяти, mtrace/muntrace...

anonymous
()
Ответ на: комментарий от MaratIK

ну valgrind'у тоже нельзя на 100 процентов доверять. invalid read встречается очень часто, и часто же это ошибка в вычислениях самого valgrind.

по поводу потеряной памяти в этом логе, это может быть и память выделяемая внутри glibc, а валгринд ее интерпретирует как утечку

ott ★★★★★
()

>...можно прочитать, перейдя по ссылке.

Акстись!

anonymous
()
Ответ на: комментарий от MaratIK

> особенно печалят строки по завершению программы:

а почему вы считаете, что перед завершением программы нужно освобождать память? это не утечки.

dea
()
Ответ на: комментарий от anonymous

про всякие другие средства будет написано в продолжении статьи :-)

ott ★★★★★
()
Ответ на: комментарий от dea

>> особенно печалят строки по завершению программы:

>а почему вы считаете, что перед завершением программы нужно освобождать память? это не утечки.

Любой malloc без парного free это утечка.

Absurd ★★★
()

Да, софтина хороша и полезна. Статья тож полезна и хороша!

ierton ★★
()
Ответ на: комментарий от dea

>а почему вы считаете, что перед завершением программы нужно освобождать память? это не утечки.

я считаю это плохим стилем программирования и не понимаю, почему есть необходимость в том, чтобы оставлять невысвобожденные куски память перед завершением процесса. Неужели разработчики не догадываются о _atexit/__cxa_atexit (последнее доступно еще со времен glibc 2.2)?

MaratIK
()
Ответ на: комментарий от Zuljin

> Каждый программист обязан научиться работать с памятью, а не с подобными костылями.

Valgrind -- это не только memory debugger. Там много вкусного есть. Cachegrind, например, который позволяет проанализировать "промахи" мимо процессорного кэша. Очень полезно для "числодробильных" задач (для одной из моих минимазация этих промахов подняла поизводительность на ~20%).

И утечки -- это, к сожалению, не только и не столько неумение работать с памятью. Это плата за скорость (когда за скорость разработки, когда за скорость исполнения). В первом случае это приводит к менее качественному коду напрямую. Во втором это приводит к более сложному коду, где больше мест для ошибок, и как следствие снова падает качество.

И подобные тулзы сильно помогают удержать его (качество) на нормальном уровне.

Важно только использовать их с умом и думать. Повторяю: _думать_!!! Ибо они не более, чем помошники, автоматизирующие рутину, а думать всё-таки должен человек.

P.S. Жаль, что во FreeBSD его "повалили"... И пока просвета не видно :-(

awn
()
Ответ на: комментарий от MaratIK

>>а почему вы считаете, что перед завершением программы нужно освобождать память? это не утечки.

> я считаю это плохим стилем программирования и не понимаю, почему есть необходимость в том, чтобы оставлять невысвобожденные куски память перед завершением процесса. Неужели разработчики не догадываются о _atexit/__cxa_atexit (последнее доступно еще со времен glibc 2.2)?

И как вы прикажете из atexit эти участки освобождать? Держать все указатели в глобальных переменных?

Второй вопрос: а вы уверены, что, на момент сработки atexit код "деструктора" (не обязательно именно деструктора в смысле C++, а просто код, который финализирует/разрушает объект), не будет уже выгружен? Не забывайте, dlopen и аналоги ещё никто не отменял.

Третий вопрос: а когда все эти atexit срабатывают? (Подсказка: стандарт описывает только поведение для однопоточного процесса)

Четвёртый вопрос (с которого всё и начиналось): _почему_ вы считаете это утечками. Или, перефразируя, почему вы считаете это плохим стилем? Только не надо доходить до абсурда в духе "дети дураки и правильное применение goto для них слишком сложно. Посему скажем, что gotо в C нет." С таким же успехом тогда надо говорить, что в C++ нет exceptions, поскольку правильное их применение тоже не тривиально. Это я к тому, что если какая-то концепция или свойство языка и/или OS сложнее 2+2, то это не повод от неё отказываться и объявлять запретной/грязной/плохим стилем.

awn
()

а на jvm можно его натравить и посчитать кэш промахи?

anonymous
()
Ответ на: комментарий от awn

это утечки. память выделяется в момент создания окна, но не высвобождается при закрытии. соответственно, приложение, жонглирующее окнами (даже простыми диалоговыми как Find/Open/Save/About...), протекает по памяти. так же имеются утечки при загрузке переводов, т.е. если пользователь часто меняет язык интерфейса на лету, то прога поимеет потенциальные проблемы с невысвобожденной памятью.

__cxa_atexit гарантирует запуск в том порядке, в каком вызывалась эта функция, будь она вызвана даже из разных потоков, и тут уже проблема програмиста синхронизировать ее вызов из разных потоков, т.к. применяя многопоточное программирование в C/C++, он возлагает на себя обязанности по правильной синхронизации потоков, и никакой компилятор за него не решит эту проблему.

Qt много чего держит в глобальных переменных, пусть часть из них и объявлены статиками. Так что держать глобально указатели для ресурсов(здесь как раз поможет магическое слово static) не будет большой проблемой.

MaratIK
()
Ответ на: комментарий от MaratIK

Это НЕ утечки. Утечки - это то, что "difinitly/possibly lost", да и то второе не обязательно.

__cxa_atexit() в каком стандарте описано?

anonymous
()
Ответ на: комментарий от MaratIK

> это утечки. память выделяется в момент создания окна, но не высвобождается при закрытии. соответственно, приложение, жонглирующее окнами (даже простыми диалоговыми как Find/Open/Save/About...), протекает по памяти. так же имеются утечки при загрузке переводов, т.е. если пользователь часто меняет язык интерфейса на лету, то прога поимеет потенциальные проблемы с невысвобожденной памятью.

Совершенно не собираюсь спорить по поводу данного конкретного случая. Мой пост относился не к Qt, а к вашему мнению, что вся память должна _обязательно_ освобождаться перед выходом вручную. Что оправдано не во всех случаях.

> _cxa_atexit гарантирует запуск ...

Во первых, никто не гарантирует наличие самого __cxa_atexit. По крайней мере ни стандарт C, ни стандарт C++, ни SUSv3 ничего про него не знают. Его наличие в GNU Libc -- это только его наличие в GNU Libc, каковая используется далеко не во всех Unix'ах (лично мне на ум кроме Linux и Hurd ничего больше в голову не приходит).

> ... в том порядке, в каком вызывалась эта функция, будь она вызвана даже из разных потоков

Порядок вызова функций, зарегистрированных в atexit (любом atexit, хоть __cxa, хоть как угодно), тут как раз дело десятое. Бо'льшая проблема -- это время вызова этих функций (ещё раз: помните про dlopen) и контекст (от имени какого thread'а она запускается). Очень интересные вещи получается, если их (thread's и dlopen) скомбинировать вместе. Ещё более интересные получаются, если вспомнить, что threads бывают ещё и detached. Ещё интереснее становится, если и threads и модули находятся вне твоего контроля, когда "ты" -- это библиотека, которую могут прилинковать куда угодно, и использовать в том окружении, где удобно разработчику, а не "тебе".

Это всё я к тому, что "серебряной пули" нет. И не будет. И __cxa_atexit хоть и может помочь в некоторых, достаточно узких случаях, панацеей не является. Как, собственно, и любой другой подход тоже.

> Qt много чего держит в глобальных переменных, пусть часть из них и объявлены статиками. Так что держать глобально указатели для ресурсов(здесь как раз поможет магическое слово static) не будет большой проблемой.

А вот это (много что в глобальных переменных) -- это уже вопрос самого Qt.

Применительно же к языкам (человеческим, как то русский, английский и т.п.), это может быть один из вариантов оптимизации. По умолчанию (отключается) Glib, например, кэширует открытые "конверторы" (iconv descriptors) и шарит их между всеми приложениями пользователя.

Не скажу про Qt, но может там происходит то же самое?

awn
()

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

Но:

1. Вообще-то, писать на Си большие проекты - дурость, как неоднократно было здесь говорено. "Большой" - это примерно тот размер, когда появляются труднообнаружимые утечки памяти.

2. И если уж писать большие проекты на Си, то хотя бы использовать libgc.

3. Также помогает прикручивание libgс к уже готовым большим проектам, страдающим от утечек или, того хуже, двойных освобождений памяти (-DREDIRECT_MALLOC=GC_malloc и т. д.).

4. На собственном опыте неоднократно убеждался, что GC нередко приводит даже к более высокой производительности, чем ручное malloc/free.

5. На худой конец, никто не мешает использовать GC и malloc/free параллельно, как это делается, например, в Inkscape.

ЗЫ А сам давно поклал на Си, работаю теперь с Питоном, доволен.

anonymous_11112
()
Ответ на: комментарий от anonymous

> Это НЕ утечки. Утечки - это то, что "difinitly/possibly lost", да и то второе не обязательно.

Не стОит так категорично. Обычно, да, это не утечки, но бывает и иначе. Например, если используется какой-нибуть allocator, который держит у себя (в адресном пространстве Вашей программы) таблицу распределённых/отданных блоков. Valgrind будет видеть, что блок достижим и на него есть ссылка. Но с прикладной точки зрения этот блок всё-таки вполне может быть "потерянным" в смысле, что он не будет отдан/использован повторно. (если пользователь не вызвал соотв. аналог free(), конечно)

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

awn
()
Ответ на: комментарий от anonymous_11112

Зачем же так громко афишировать свою некомпетентность? И рассказывать истории своих личных провалов? Причем с менторским выражением в голосе :)

Писать на Си большие проекты - дурость? :) Кажется, когда речь заходит о языках, все дружно забывают, о чем тут вообще идёт речь на данном ресурсе. Напоминаю, о linux. Так вот, ядро линукс, кто еще не в курсе, написано на языке Си и является не просто большим, а огромным и успешным проектом, берите уже, наконец, пример :)

Displacer ★★
()
Ответ на: комментарий от Displacer

А ты, умный.

1. Если бы сегодня мне предложили написать Линукс, я бы выбрал BitC, слегка его допилив. Если бы не было BitC, подумал бы насчёт Ады какой-нибудь. На саааамый худой конец написал бы свой спецнедоязычок, транслируемый в Си. Линукс и драйверы пишутся на сях не оттого, что си рулят, а как обычно, по инерции.

2. Второй по значению после ядра линукса массив сишного кода - это GTK+ и сопутствующие товары. И думаете от хорошей жизни появляется Vala и всякие Gtk#? Писать на голых сях никто не хочет, и я не удивлён.

3. (не сочтите за оффтоп) Венда активно переходит на дотнет. Да и без дотнета на голых сях под неё дааааааавно людям расхотелось писать.

4. Из других больших проектов на сях я встречал только различное корпоративное говно, которое просто никто не в состоянии переписать. Лично участвовал в портировании одного куска такого говна с C/Motif на Python/PyQt с крошечными вставками на C и C++. Размер кода сократился раз в 10, быстродействие _выросло_, потребление памяти _снизилось_. Потому что старый код, как было сказано, был унылым корпоративным говном. А был он им потому, что Си не предоставляет достаточного уровня абстракции для написания таких вещей. Он, к счастью, обладает ограниченными возможностями по созданию своих DSL, но они, я не преувеличиваю, ограничены чуть более, чем полностью. И написание чуть менее кривого, чем обычно, кода на Си требует высокой дисциплины, свинцовых штанов и надсмотрщика с дубиной и характером Линуса. И да, большого количества времени, факт. И то нормальному разработчику через годик-другой надоест выполнять за компьютер часть его работы, и он не свалит на более высокоуровневые (читай, приближенные к человеку) языки. Да и спрос на сишников неуклонно падает, это медицинский факт, разве что ембедщики пока нужны.

anonymous_11112
()

> Каждый начинающий (и не только) разработчик на языке C просто обязан научиться пользоваться данным средством.

Да. да. Особенно если он пишет под MCS-51 или AVR :)

itanko
()
Ответ на: комментарий от anonymous_11112

Простите, но у Вас в голове каша. Рассказывать, что язык Си - отстой, мотивируя это тем, что Motiff - кусок говна, это всё равно, что сравнивать динозавра с гаечным ключом. Также, прежде, чем вспоминать язык Ада, предназначенный для военных применений, и браться с нуля написать Линукс, можно было бы найти высказывания самого Линуса о языках программирования. Сообщаю, есть четко высказанное Линусом мнение, что языки, подобные Паскалю-Аде ограничивают его свободу в написании ядра. Также появление GTK# и прочее ошибочно понимается вами как преимущества #. Думаю совсем нетрудно было найти ссылку на то, что интерфейсы для GTK+ имеются для практически любых языков программирования, и чуть ли не самым первым было gtkmm.

По поводу уровня абстракции - достаточно сказать, что Си позволяет писать ООП код, а уровень абстракции требует очень хорошего умения проектировать ПО и в неумелых руках приводит также часто к печальным последствиям, часто наблюдаемым в различных взаимозависимостях и наслоению обслуживающего кода в ущерб функциональности и сопровождаемости.

Далее, по поводу оффтопа. То, что "Венда активно переходит на дотнет". Это связано прежде всего с корпоративной ориентированностью на RAD и дешевых разработчиков, а не качество и эффективность кода. Кроме того, никто не заставляет писать GUI приложения на чистом Си - есть C++, и уж он то точно в умелых руках ничуть не страдает от нехватки GC.

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

Displacer ★★
()
Ответ на: комментарий от anonymous_11112

>>> Если бы сегодня мне предложили написать Линукс

Этого вам точно никто не предложит :)

>>> Из других больших проектов на сях

Очень странный способ выбирать язык по объёму проекта, а не по назначению. Так вы можете и ядро на каком-нибудь PHP забодяжить.

Рекомендую ознакомиться

http://www.intuit.ru/department/os/osunix/1/

sergey_vp
()
Ответ на: комментарий от sergey_vp

щас запустил с параметрами

valgrind --leak-check=full --log-file=12345 ./ice

получил :
==6545== LEAK SUMMARY:
==6545== definitely lost: 172 bytes in 1 blocks.
==6545== indirectly lost: 2,121 bytes in 6 blocks.
==6545== possibly lost: 1,409 bytes in 1 blocks.
==6545== still reachable: 173,044 bytes in 471 blocks.
==6545== suppressed: 0 bytes in 0 blocks.
==6545== Reachable blocks (those to which a pointer was found) are not

...

kto_tama ★★★★★
()
Ответ на: комментарий от Displacer

> а желания пользователей, которые хотят видеть быстрый, компактный и эффективный код еще пока никто не отменял

Пользователям код вообще до лампочки, лол. Им надо, чтобы не глючило и не тормозило. Вот к безглючности си ни разу не располагают, тут спорить не о чем. А по поводу производительности... Там, где питонщик применит хэш-таблицу, сишник в 99% случаев будет использовать последовательный перебор. И так везде. Ну и зачем писать на сях?

> Сообщаю, есть четко высказанное Линусом мнение, что языки, подобные Паскалю-Аде ограничивают его свободу в написании ядра.

Линус не знает Аду, это тоже медицинский факт. Он вообще кроме Си ничего не знает. Тебе понятие "туннельное зрение" знакомо?

> Думаю совсем нетрудно было найти ссылку на то, что интерфейсы для GTK+ имеются для практически любых языков программирования, и чуть ли не самым первым было gtkmm.

Верно. Развей же свою мысль. Зачем, по-твоему, появляются эти интерфейсы, если есть расчудесный Си?

> По поводу уровня абстракции - достаточно сказать, что Си позволяет писать ООП код, а уровень абстракции требует очень хорошего умения проектировать ПО и в неумелых руках приводит также часто к печальным последствиям, часто наблюдаемым в различных взаимозависимостях и наслоению обслуживающего кода в ущерб функциональности и сопровождаемости.

Всё с точностью до наоборот, друг мой. Во-первых, по "неумелым рукам" Си бьёт, как никто другой, хуже только плюсы. Во-вторых, в неумелых руках низкоуровневый язык куда страшнее высокоуровневого: если второй искаропки предоставляет немало толковых решений и готовых кубиков, то в первом приходится всё делать самому. В результате получаются такие наслоения, которых ты, чувствую, даже в бредовых видениях не встречал. А я с ними работал. Ты знаешь, какой код пишут индусы из IBM на чистом кошерном Си?

> Это связано прежде всего с корпоративной ориентированностью на RAD и дешевых разработчиков, а не качество и эффективность кода.

Вздор говоришь. Сложность проекта требует более мощных выразительных средств, чем те, что предоставляет Си. Дотнет, правда, не лучшее решение, но не потому, что "не кампилитсо в машкод и не Ъ", а попросту потому, что сделаны там многие вещи через жопу, в стиле микрософта. Впрочем, йабба не лучше. Но от байт-кода мы никуда не денемся, попомни моё слово лет через 10.

anonymous_11112
()
Ответ на: комментарий от sergey_vp

> Очень странный способ выбирать язык по объёму проекта, а не по назначению. Так вы можете и ядро на каком-нибудь PHP забодяжить.

Во-первых, где это я говорил, что выбираю язык по объёму проекта, а не по задаче? Очки протри.

Во-вторых, лол, про BitC почитай.

anonymous_11112
()

Однако, любопытная статья.. спасибо..

MiracleMan ★★★★★
()
Ответ на: комментарий от anonymous_11112

>>> Верно. Развей же свою мысль. Зачем, по-твоему, появляются эти интерфейсы, если есть расчудесный Си?

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

sergey_vp
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.