Perl 진단 메시지

Perl 진단 메시지 (perldiag)

이 문서는 Perl이 출력하는 다양한 진단 메시지(경고·오류)를 다뤄요. 각 메시지가 뜻하는 바와 어떻게 대응하면 좋은지 강사가 옆에서 설명하듯 알려드려요.

출처: perldoc - perldiag

본문

메시지 분류 (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)

더 깊이 보려면 다음 문서를 함께 읽어 보세요.