Perl 진단 메시지
Perl 진단 메시지 (perldiag)
이 문서는 Perl이 출력하는 다양한 진단 메시지(경고·오류)를 다뤄요. 각 메시지가 뜻하는 바와 어떻게 대응하면 좋은지 강사가 옆에서 설명하듯 알려드려요.
본문
메시지 분류 (Classification)
Perl 메시지는 절박함(desperation)이 커지는 순서대로 다음과 같이 분류돼요:
(W) A warning (optional). 경고(선택)
(D) A deprecation (enabled by default). 폐기(기본 켜짐)
(S) A severe warning (enabled by default). 심각한 경고(기본 켜짐)
(F) A fatal error (trappable). 치명적 오류(잡을 수 있음)
(P) An internal error you should never see (trappable). 내부 오류(잡을 수 있음)
(X) A very fatal error (nontrappable). 매우 치명적 오류(잡을 수 없음)
(A) An alien error message (not generated by Perl). 외계 메시지(Perl이 만들지 않음)
처음 세 분류(W·D·S)의 대부분 메시지는 warnings 프래그마로 제어할 수 있어요. 메시지가 warnings로 제어 가능하면, 아래 설명에 분류 문자와 함께 경고 카테고리가 포함돼요. 예를 들어 (W closed)는 closed 카테고리의 경고를 뜻해요.
선택적 경고는 warnings 프래그마나 -w·-W 스위치로 켜요. 경고는 $SIG{__WARN__}에 루틴 참조를 설정해 출력 대신 포착할 수도 있어요(perlvar 참고). 심각한 경고는 warnings 프래그마나 -X 스위치로 명시적으로 끄지 않는 한 항상 켜져 있어요.
잡을 수 있는 오류는 eval 연산자로 잡을 수 있어요(perlfunc 참고). 거의 모든 경우 경고는 warnings 프래그마로 선택적으로 끄거나 치명적 오류로 승격할 수 있어요(warnings 참고).
메시지는 알파벳순(대·소문자 무시)으로 나열돼요. 일부 메시지는 일반적(generic)이에요. 달라지는 자리는 %s나 다른 printf 스타일 이스케이프로 표시돼요. 이 이스케이프는 알파벳순에 포함되지 않아요. 메시지를 찾으려면 문자가 아닌 것을 모두 무시하면 돼요.
주요 진단 (Selected Diagnostics)
아래는 자주 만나는 대표 진단들을 실제 메시지 문자열 그대로 보존해 번역한 것이에요.
__CLASS__ is experimental
(S experimental::class)use feature 'class'의__CLASS__키워드를 쓸 때 나와요. 현재 실험적이며 이후 릴리스에서 동작이 바뀔 수 있어요.
accept() on closed socket %s
(W closed)닫힌 소켓에 accept를 시도했어요.socket()의 반환 값을 확인했나요? perlfunc.
Aliasing via reference is experimental
(S experimental::refaliasing)할당의 왼쪽에 참조 생성자를 써서 변수를 다른 변수의 별명으로 만들 때 나와요. 경고를 끄고 쓰고 싶다면:no warnings "experimental::refaliasing"; use feature "refaliasing"; \$x = \$y;
'%c' allowed only after types %s in %s
(F)!·<·>수정자는 pack()/unpack()에서 일부 타입 뒤에서만 허용돼요. pack 참고.
Ambiguous call resolved as CORE::%s(), qualify as such or use &
(W ambiguous)선언한 서브루틴이 Perl 키워드와 이름이 같고, 한쪽을 부르기 위해 이름을 수식 없이 썼어요. 서브루틴이 import되지 않아 Perl이 내장 함수를 부르기로 했어요. 서브루틴 호출로 강제하려면 이름 앞에&를 붙이거나 패키지로 수식하세요. Perl 연산자로 조용히 해석하게 하려면CORE::접두사를 쓰세요(예:CORE::log($x)).
Ambiguous range in transliteration operator
(F)tr/a-z-0//같은 무의미한 걸 썼어요. transliteration에-를 넣으려면 처음이나 끝에 두세요. (tr/a-z-0//는 예전엔tr/a-y//와 동의어였어요.)
Ambiguous use of -%s resolved as -&%s()
(S ambiguous)-foo처럼 썼는데, 이는 문자열"-foo"이거나 함수foo를 부정한 호출일 수 있어요. 문자열을 의도했다면"-foo"로, 함수 호출을 의도했다면-foo()로 쓰세요.
Argument "%s" isn't numeric%s
(W numeric)숫자를 기대하는 연산자에 문자열을 인자로 넣었어요.Inf·NaN의 경우 "숫자"의 정의가 특이해요: 그 문자열 자체("Inf" 등)는 숫자로 취급되고 그 뒤는 비숫자로 취급돼요.
Argument "%s" treated as 0 in increment (++)
(W numeric)++가 숫자나/^[a-zA-Z]*[0-9]*\z/에 맞는 문자열을 기대하는데 그런 인자를 받았어요. 자동 증가·감소.
Array passed to stat will be coerced to a scalar%s
(W syntax)배열에 stat()을 호출했는데 배열이 스칼라(요소 수)로 강제돼요.
A signature parameter must start with '$', '@' or '%'
(F)각 시그니처 파라미터 선언은 유효한 시길로 시작해야 해요:sub foo ($x, $, $y = 1, @z) {}
A named signature parameter must start with '$'
(F)이름 붙은 파라미터는 스칼라 시길로 시작해야 해요:sub foo (:$x, :$y, :$z) {}배열·해시 변수는 이름 붙은 파라미터로 허용되지 않아요.
A slurpy parameter may not have a default value
(F)스칼라 시그니처 파라미터만 기본값을 가질 수 있어요:sub foo ($x = 1) {} # legal sub foo (@x = (1)) {} # invalid sub foo (%x = (a => b)) {} # invalid
Assigned value is not a reference
(F)참조가 아닌 값을 lvalue 참조에 할당했어요(예:\$x = $y).$x를$y의 별명으로 만드려면\$x = \$y를 쓰세요.
Assigned value is not %s reference
(F)참조 생성자에 참조를 할당했는데 두 참조 타입이 달라요. 스칼라를 배열에, 배열을 해시에 별명 붙일 수 없어요:\$x = \@y; # error \@x = \%y; # error
Assigning non-zero to $[ is no longer possible
(F)"array_base" 기능이 비활성일 때(예:use v5.16;아래, 5.30 이후) 폐기된 특수 변수$[는 고정된 0값이에요.
Assuming NOT a POSIX class since %s in regex; marked by <-- HERE in m/%s/
(W regexp)[[:alnum]]처럼 POSIX 클래스로 보이지만 유효하지 않은 걸 썼어요. POSIX 클래스를 의도했다면[[:alnum:]]처럼 쓰세요.
<> at require-statement should be quotes
(F)require 'file'로 써야 할 것을require <file>로 썼어요.
Attempt to access disallowed key '%s' in a restricted hash
(F)제한된 해시(restricted hash)의 허용 키 집합에 없는 키에 접근(설정·취득)하려 했어요.
Attempt to bless into a freed package
(F)어떤 이유로 현재 패키지가 해제된 뒤 인자 하나로bless $foo를 썼어요.
Attempt to bless into a class
(F)새 스타일class의 패키지 이름으로bless를 호출하려 해요. 생성자가 만든 인스턴스는 이미 올바른 클래스에 있으니 필요 없지만,bless같은 다른 수단으로 인스턴스를 만들 수는 없어요.
Attempt to bless into a reference
(F)bless()의 CLASSNAME 인자는 객체를 bless 할 패키지 이름이어야 하는데 참조를 넘겼어요. 아마bless $self, $proto;로 썼는데bless $self, ref($proto) || $proto;를 의도했을 거예요.
Can't locate Module.pm in @INC ...
(F)use Module;나require에서 모듈을@INC에서 찾지 못했어요. 모듈 설치·PERL5LIB·use lib경로를 확인하세요.
syntax error
(F)문법 오류. 괄호·따옴표·연산자 누락이 흔한 원인이에요.-c로 문법만 검사해 볼 수 있어요.
Bareword "foo" not allowed while "strict subs" in use
(F)strict subs가 켜진 상태에서 따옴표 없는 베어워드를 함수처럼 썼어요.
Undefined subroutine &main::foo called
(F)정의되지 않은 서브루틴을 호출했어요. 오타나 누락된use를 확인하세요.
Use of uninitialized value $x in string ...
(W)초기화되지 않은 값을 연산에 썼어요. 값을 넣기 전에 읽었을 때 나와요.//(정의 연산자)나defined로 기본값을 주면 깔끔해요.
Redefinition of sub foo
(W)이미 정의된 서브루틴을 다시 정의했어요. 모듈을 중복require했을 때 흔해요.
panic: ...
(P)Perl 내부 불변식이 깨졌어요. 대부분 Perl 버그나 C·XS 확장의 잘못된 메모리 다룸이 원인이에요.
경고 켜고 끄기 (Controlling Warnings)
use warnings; # 경고 켜기
use warnings "uninitialized"; # 특정 카테고리만
no warnings "deprecated"; # 특정 카테고리 끄기
치명적 오류는 eval로 잡을 수 있어요:
eval { risky_code() };
warn $@ if $@;
완전한 목록 (The Full List)
이 문서는 perldoc perldiag의 분류 체계와 대표 진단을 번역·정리한 것이에요. 수천 개의 전체 메시지에 대한 알파벳순 완전 목록과 각각의 상세 설명·예시는 perldoc - perldiag 또는 소스 트리의 perldiag.pod에 있습니다. 거기서 각 메시지는 위 규칙대로 분류 기호와 카테고리가 함께 수록되어 있어요.
더 알아보기 (Learn more)
더 깊이 보려면 다음 문서를 함께 읽어 보세요.