함수의 동적 생성 및 호출은 Perl의 가장 유연한 메커니즘 중 하나로, 라텍스 및 셸 스크립트의 전통을 계승하고 있습니다. 초기 버전부터 Perl은 문자열을 통해 함수 호출(상징적 링크/globs), 변수 및 연관 배열에 서브프로그램의 링크 저장을 허용하며, AUTOLOAD 구문을 통해 즉석에서 함수를 생성할 수 있습니다.
이 접근 방식의 주요 문제는 보안(제대로 지정되지 않은 문자열에 의해 원하지 않는 함수를 호출할 가능성) 및 성능(상징적 이름 확인이 직접 호출보다 느림)입니다. 함수의 범위 및 올바른 인수 수의 전달을 제어하는 것도 중요합니다.
해결책은 해시 디스패처(문자열/키워드에서 코드를 참조하는 매핑)를 사용하고, 사용자 코드를 실행하기 위해 eval을 피하며, 호출할 수 있는 함수 목록을 명확히 정의하는 것입니다.
코드 예제(키에 의한 디스패칭):
my %dispatch = ( add => sub { $_[0] + $_[1] }, sub => sub { $_[0] - $_[1] }, mult => sub { $_[0] * $_[1] }, ); my $key = 'add'; if (exists $dispatch{$key}) { print $dispatch{$key}->(2, 3); # 5를 출력합니다. } else { die "알 수 없는 작업 $key"; }
주요 특징:
문자열만 사용하여 함수 이름으로 함수 호출이 가능한가요?
답변: 가능하지만 위험합니다. 외부(사용자) 데이터와 함께 $fn_name->() 호출이나 직접 상징적 링크 &$fn_name(); 사용은 권장되지 않습니다. 이는 잠재적인 취약점을 초래하기 때문입니다.
Perl에서 코드 참조와 함수 이름 사이의 차이가 있나요?
답변: 예, 함수 이름은 항상 전역적이고, 함수에 대한 링크(코드 참조)는 렉시컬, 로컬일 수 있으며 서브프로그램 간에 전달되고 익명 함수를 저장할 수도 있습니다.
my $coderef = sub { ... }; my $named = \&fn_name;
해시 디스패처를 통해 존재하지 않는 함수를 호출하면 어떻게 되나요?
답변: 키가 없으면 오류가 발생합니다. 따라서 호출 전에 항상 exists를 확인하고 인식되지 않은 명령을 처리해야 하며, 그렇지 않으면 undef를 호출하려고 시도하게 되어 치명적인 오류가 발생합니다.
웹사이트의 명령이 GET 파라미터에서 함수 이름을 받아 eval을 통해 호출합니다. 이는 모든 사용자가 system, unlink 및 기타 위험한 함수를 호출할 수 있게 합니다.
장점:
단점:
함수의 화이트리스트 해시를 사용하고 모든 매개변수를 검증하며, eval을 사용하지 않고 오류를 포착하여 기록합니다.
장점:
단점: