프로그래밍백엔드/풀스택 개발자

Perl의 내장 가비지 수집기 작업 메커니즘에 대해 설명하십시오. Perl은 언제 불필요한 메모리를 해제하고 누수가 발생합니까?

Hintsage AI 어시스턴트로 면접 통과

답변

Perl은 자동 메모리 관리를 위해 참조 카운트 알고리즘을 사용합니다: 각 변수에는 참조 카운트가 있습니다. 참조 카운트가 0이 되면 메모리가 해제됩니다. 대부분의 경우 이는 투명하게 작동하며 — 사용하지 않는 변수는 범위를 벗어날 때 자동으로 삭제됩니다.

문제는 순환 참조가 발생할 때 발생합니다 (예: 객체가 자기 자신을 참조하거나 두 구조가 서로를 참조하는 경우). 이 경우 참조 카운트는 결코 0이 되지 않으며 메모리가 해제되지 않습니다.

누수를 방지하기 위해 Scalar::Util::weaken 모듈을 사용합니다 — 이는 참조 카운트를 증가시키지 않는 "약한" 참조를 생성할 수 있게 합니다.

예제:

use Scalar::Util qw(weaken); my $a = {}; my $b = { ref => $a }; $a->{ref} = $b; weaken($a->{ref}); # 이제 순환 강한 의존성이 없습니다.

덫 질문

Perl이 복잡한 상호 연관 구조가 있더라도 항상 자동으로 모든 사용하지 않는 메모리를 해제한다고 가정하는 것이 맞습니까?

답변 및 예제:

아니요! 순환 참조의 경우 Perl은 weaken을 사용하지 않으면 메모리를 자동으로 해제할 수 없습니다:

my $a = {}; $a->{self} = $a; # 순환 # $a는 자동으로 삭제되지 않으며 — 수동으로 끊거나 참조를 약화시켜야 합니다.

주제에 대한 잘 모르고 발생한 실제 오류 사례


이야기 1: 대규모 Perl 웹 서비스에서 메모리 누수가 발생했습니다 — 사용자 세션이 해시에서 서로를 참조하고 있었으며 누군가가 약한 참조를 사용하지 않았습니다. 서비스는 하루가 지나면서 모든 자원을 소모하며 중단되고 재시작이 필요했습니다.


이야기 2: 사용자 및 그룹 객체 간에 순환을 생성하는 자체 작성 ORM이 있었으며, 각각 서로를 참조하고 있었습니다. 범위를 벗어난 후 객체는 메모리에 남아 있었고 — 서비스는 점차 수십 기가바이트까지 "부풀어 올랐습니다!"


이야기 3: $self를 참조하는 클래스 메소드로서 익명 서브 프로그래밍(“클로저”)을 사용할 때 각 객체 생성 시 누수가 발생하며, 이후 분석기가 순환 참조를 발견하고 weaken의 필요성을 지적할 때까지 문제였습니다.