역사적으로 Perl은 변수의 렉시컬 범위를 지원하므로 클로저(closures) — 외부 환경을 저장하는 함수들을 사용할 수 있습니다. 클로저가 자신의 범위를 벗어난 변수를 참조하거나 중첩된 구조가 순환 참조를 생성하는 경우 메모리 누수가 발생하는 문제가 발생합니다.
해결책은 변수를 외부 범위에서 클로저할 때 링크를 올바르게 관리하는 것을 기억하며 함수 공장을 만들고 함수형 스타일로 클로저를 사용하는 것입니다.
코드 예시:
sub make_counter { my $count = 0; return sub { $count++; }; } my $counter = make_counter(); print $counter->(), " "; # 0 print $counter->(), " "; # 1
주요 특징:
자신을 참조하는 익명 함수를 반환하면 어떻게 될까요?
순환 참조가 생성되며 Perl은 이를 자동으로 가비지 컬렉터로 수집할 수 없습니다. 이는 메모리 누수로 이어집니다. 해결책으로는 약한 링크를 사용하십시오, 모듈 Scalar::Util:
use Scalar::Util qw(weaken); my $foo; $foo = sub { ... $foo ... }; weaken($foo);
클로저는 항상 변수의 «복사본»을 캡처하나요, 아니면 같은 변수를 참조하나요?
클로저는 항상 현재 변수를 조작하며, 그 범위는 클로저가 생성될 때 고정됩니다. 따라서 모든 클로저 함수 호출에서 변수는 동일합니다.
클로저가 자신 외부의 가변 상태와 함께 작동하도록 하고, 해당 상태에 대한 강한 참조를 유지하지 않도록 할 수 있나요?
네, 약한 링크(Scalar::Util::weaken)를 사용하거나 링크가 필요한 곳에서만 링크를 유지하도록 코드를 구조화하십시오(예: 각 클로저 호출 시 데이터를 외부에서 전달).
OO 객체에서 $self를 클로저로 캡처한 콜백 클로저를 생성하고 콜백의 해시 내에 유지합니다. 객체가 파괴된 후 메모리가 해제되지 않습니다.
장점:
단점:
Closure가 Scalar::Util::weaken를 통해 $self에 대해 올바르게 약한 참조를 유지합니다:
use Scalar::Util qw(weaken); my $cb = sub { my $self = shift; weaken($self); ... };
장점:
단점: