Есть ли в Perl v5.10.1 утечки памяти или как интерпретировать valgrind?
У меня есть скрипт, который имеет утечки памяти. Я считаю, что это так, потому что после того, как я выполняю undef
на моих вложенных объектах объем памяти в скрипте не изменяется. Я использовал Devel::Cycle, чтобы найти любые циклические ссылки, и я превратил эти циклические ссылки в слабые ссылки с Scalar::Util
, Проблема все еще остается.
Сейчас я пытаюсь использовать Valgrind для решения этой проблемы. В качестве первого начала работы с valgrind я протестировал программу Perl Hello World:
#! /usr/bin/perl
use strict;
use warnings;
print "Hello world!\n";
Здесь был вывод valgrind при запуске valgrind --trace-children=yes perl ./hello_world.pl
:
==12823== HEAP SUMMARY:
==12823== in use at exit: 290,774 bytes in 2,372 blocks
==12823== total heap usage: 5,159 allocs, 2,787 frees, 478,873 bytes allocated
==12823==
==12823== LEAK SUMMARY:
==12823== definitely lost: 13,981 bytes in 18 blocks
==12823== indirectly lost: 276,793 bytes in 2,354 blocks
==12823== possibly lost: 0 bytes in 0 blocks
==12823== still reachable: 0 bytes in 0 blocks
==12823== suppressed: 0 bytes in 0 blocks
==12823== Rerun with --leak-check=full to see details of leaked memory
==12823==
==12823== For counts of detected and suppressed errors, rerun with: -v
==12823== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
Насколько я понимаю, отсюда, что когда число allocs
не равно количеству frees
у вас утечка памяти
Поскольку все, что я делаю, - это печать hello world, я вынужден задать вопрос, имеет ли по крайней мере сам интерпретатор Perl, здесь v5.10.1, утечка памяти, или я все неправильно интерпретирую?
Я хотел бы понять это, прежде чем приступить к работе с моим настоящим Perl-скриптом.
ДОПОЛНЕНИЕ
Я вижу в Perl 5.12.0 delta следующее:
Слабая ссылка на хеш будет утечка. Это влияло на DBI [RT #56908].
В конечном итоге это может относиться к моему полному сценарию perl, а не к этой программе hello world, но это наводит меня на мысль о том, что я должен пройти через установку последней версии perl без полномочий root.
ADDENDUM2
Я установил ActiveState Perl 5.16.3, и проблема, а также проблемы моего реального скрипта, все еще остается.
Я подозреваю, что в случае этой программы hello world я, должно быть, неправильно использую / интерпретирую valgrind, но пока не понимаю, где.
ОБНОВЛЕНИЕ1 Ответ Даксима действительно имеет значение. Когда я ввожу следующую строку в моем скрипте Perl:
use Perl::Destruct::Level level => 1;
Тогда вывод valgrind будет таким:
==29719== HEAP SUMMARY:
==29719== in use at exit: 1,617 bytes in 6 blocks
==29719== total heap usage: 6,499 allocs, 6,493 frees, 585,389 bytes allocated
==29719==
==29719== LEAK SUMMARY:
==29719== definitely lost: 0 bytes in 0 blocks
==29719== indirectly lost: 0 bytes in 0 blocks
==29719== possibly lost: 0 bytes in 0 blocks
==29719== still reachable: 1,617 bytes in 6 blocks
==29719== suppressed: 0 bytes in 0 blocks
==29719== Rerun with --leak-check=full to see details of leaked memory
==29719==
==29719== For counts of detected and suppressed errors, rerun with: -v
==29719== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
Что является существенной разницей. Мои проблемы утечки памяти с моим сценарием остаются, но, по крайней мере, эта программа hello world теперь кажется разумной для valgrind.
Однако все это заставляет задуматься о том, какой смысл останавливать жесткие циклические ссылки Scalar::Util
если память не освобождается до выхода из программы, исключая использование этого несколько эзотерического Perl::Destruct::Level
модуль???
2 ответа
Утечка преднамеренная. Винсент в #p5p комментариях:
Выделенная память фактически не освобождается, если не задан PERL_DESTRUCT_LEVEL, потому что операционная система быстрее справится с этим. PERL_DESTRUCT_LEVEL доступен только для отладки сборок или с помощью Perl::Destruct::Level от perl.
Насколько я понимаю (и, пожалуйста, поправьте меня, если я ошибаюсь - я не читал код, а документация кажется довольно скудной), дело в том, что в типичной программе на Perl есть много вещей, которые будут выделено, но оно не будет освобождено до завершения программы. Это включает в себя такие вещи, как глобальные переменные, а также, например, сам код скомпилированной программы.
Теперь Perl может освободить память, используемую для всех этих вещей, когда программа заканчивается, но оказывается, что обычно нет особого смысла, так как ОС все равно сделает это. Единственным исключением является случай, когда что-то вроде valgrind ищет, не осталось ли свободной памяти в конце программы, и предполагает, что любая такая память, должно быть, была утечка.
Так что, по сути, perl обычно ленив и не будет беспокоиться об освобождении памяти, когда знает, что вот-вот выйдет и позволит ОС позаботиться об этом. Установка PERL_DESTRUCT_LEVEL говорит Perl очистить эту память в любом случае, просто чтобы показать инструментам вроде valgrind, что она на самом деле не была утечка.
Во всяком случае, ничего из этого, AFAIK, не влияет на управление памятью во время выполнения программы. Если вы уменьшите счетчик ссылок до нуля во время работы программы (например, выпустив переменную из области видимости или напрямую перезаписав последнюю ссылку), она освободится независимо от PERL_DESTRUCT_LEVEL.
Тем не менее, обратите внимание, что это обычно освобождает память для повторного использования самим Perl - за исключением некоторых редких случаев, таких как явный mmap(), для любой программы, работающей в современной ОС с виртуальной памятью, довольно необычно фактически высвобождать страницы памяти обратно в ОС. пока он работает