LINUX.ORG.RU

[Perl] Крохотный вынос мозга

 


0

1

Как это работает?

sub retLnk2Arr { 
my $a;
push @$a,(1,2,3,4);
return $a;
};
print retLnk2Arr->[2];
Внимание, вопрос: как умудряется выживать по ссылке $a массив (список) между вызовами функций?
Насколько я помню, в ассемблере все локальные переменные функции принято хранить в стеке, из которого по выходу из функции всё нафиг выталкивается. И вообще там область данных функции не принято использовать извне (те же данные в стеке). А тут как? Анонимный массив создаётся внутри функции, а используется по ссылке ИЗВНЕ!

★★★★★

Это ж perl. GC подсчетом ссылок, пока есть живые ссылки - память не освобождается.

AptGet ★★★
()

>в ассемблере
где тут ассемблер?

в ассемблере все локальные переменные функции принято хранить в стеке

а если у тебя переменная больше чем стек?

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

>а если у тебя переменная больше чем стек?
И что? В стек заталкивается ссылка на область памяти. Но область памяти должна бы освобождаться по выходу.

Ну и как бы namespace кто-то уже отменил? С какого перепугу глобальный namespace обращается к данным, инициализированным внутри функции? Оно как бы память не теряет после каждого вызова таким образом?
А то, представьте, функция создаёт анонимный массив из 10000 элементов, память при выходе не освобождает, я потом эту функцию вызываю 10000 раз - и что, в итоге 10000*10000 элементов у меня будет тупо заблокировано для malloc'а?!

DRVTiny ★★★★★
() автор топика

> как умудряется выживать по ссылке $a массив (список) между вызовами функций?

в примере — не локальный массив, а «смертный» объект (создается при первой попытке «разыменования»; заполняется push'ком). как только количество ссылок на него будет равно нулю, он будет съеден сборщиком падалимусора. но пока на него есть хоть одна ссылка, он будет жить.

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

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

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

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

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

Блин, небось не в начале блока, а в самом указателе... Кстати, это неправильно вообще: теоретически можно создать указатель на переменную, который будет утыкаться в область памяти, где на самом деле лежит список. Если бы при этом ещё возвращался первый элемент списка :(

DRVTiny ★★★★★
() автор топика

>в ассемблере

А в вижуалбейсике как?

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

ты вообще был в сознании, когда писал этот пост?

man perl
/Internals and C Language Interface

и дальше все маны по списку.

arsi ★★★★★
()

Ты что сказать хотел? Ты передаешь наружу ссылку на массив. Если вызовешь функцию два раза - получишь две ссылки на разные массивы. То что в C можно передать указатель на массив тебя же не смущает? Тут то же самое.

Vovka-Korovka ★★★★★
()
sub make_hello_printer {
my $message = "Hello, world!";
return sub { print $message; }
}

my $print_hello = make_hello_printer();
$print_hello->()

взрывать, так взрывать

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

>А вы не в курсе, как вообще эти области памяти инициализируются? В начале блока стоит дескриптор какой-то, описывающий, что идёт за ним? В Perl нет типов данных, но по крайней мере ссылку на переменную и ссылку на список различать нужно. А Perl различает ещё и ссылку на массив и ссылку на хэш, хотя по сути список и хэш хранятся одинаково (просто в хэше количество элементов всегда чётное)??

Честно говоря, вот так сходу я не смогу ответить, как там все внутри устроено. :) Насчет хеша и массива - хранятся они по разному, если попробовать разыменовать ссылку на массив как ссылку на хеш, можно получить подобное сообщение: «Can't coerce array into hash»

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

>взрывать, так взрывать

Это же замыкание :)

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

>взрывать, так взрывать

Ну а ты чего хотел от такого кода? Хотя пример прикольный.

Vovka-Korovka ★★★★★
()
Ответ на: комментарий от DRVTiny

Слушай, откруй уже сорцы и посмотри.

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

Ссылки на данные типа typeglob

Компилятор Perl хранит имена всех переменных программы в таблице символов. Отдельная таблица символов существует для каждого пакета, образуя собственное пространство имен.

(О пакетах и таблицах символов рассказывается в части 12.)

Каждый идентификатор, встречающийся в пакете, заносится в таблицу символов. Одинаковые идентификаторы, соответствующие переменным разных типов, образуют гнездо, в котором каждому типу соответствует свой элемент, содержащий адрес переменной данного типа. Если, например, в программе имеются следующие строки

ну и так далее

http://www.realcoding.net/teach/perl/9/Index2.htm

anonymous
()

Во вещь, а главное - раскрывает истину много-много раз!

 perl -e 'my $c=1; sub retHshLnk { %hsh=(strana=>"Liviya",agressor=>"NATO",nraket=>$c); $c++; return \%hsh; }; while (my ($key,$value)=each %{&retHshLnk}) { print "$key=$value\n"; }'

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

Какая из?:) Старая добрая ручная на пакетах? Ну, это же не реализация ООП, а скорее набор инструментов для реализации ООП:) На cpan не мало разных подходов, все они забавные:)

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