@luzluna - C,Perl 엔지니어. 근래엔 Ops에 더 가까운 DevOps. PostgreSQL 성능 최적화의 공동 역자, luzluna at gmail.com
첫 번째 기사에서는 펄이 어떻게 스칼라 변수를 내부적으로 처리하는지를, 두 번째 기사에서는 펄의 기본타입인 스칼라변수가 어떻게 내부적으로 표현되는지 문맥에 따라 어떻게 변화되는지를 살펴보았습니다. 오늘은 펄의 또다른 기본 타입인 배열 변수와 해시 변수에 대해 살펴봅니다.
일단 빈 배열 변수를 하나 만들고 살펴보겠습니다.
use Devel::Peek; @array; Dump(\@array);
결과를 살펴보죠.
SV = IV(0x7fd4308044a8) at 0x7fd4308044b8 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7fd430829690 SV = PVAV(0x7fd430806398) at 0x7fd430829690 REFCNT = 2 FLAGS = () ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x0 FLAGS = (REAL)
@array
라는 변수는 IV
타입으로 생성되었고 FLAGS
에는 ROK
그리고 RV
에는
실제 PVAV
타입의 배열을 저장한 곳을 가리키고 있음을 알 수 있습니다.
ARRAY
는 0x0
그리고 MAX
와 FILL
은 -1
로 표시되어있군요.
비어있다는 의미겠죠?
값을 넣어보겠습니다.
use Devel::Peek; @array; print "# push 전\n"; Dump(\@array); push(@array, 1); print "# push 후\n"; Dump(\@array);
결과를 살펴보죠.
# push 전 SV = IV(0x7fc1620044a8) at 0x7fc1620044b8 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7fc162029690 SV = PVAV(0x7fc162006398) at 0x7fc162029690 REFCNT = 2 FLAGS = () ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x0 FLAGS = (REAL) # push 후 SV = IV(0x7fc162004658) at 0x7fc162004668 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7fc162029690 SV = PVAV(0x7fc162006398) at 0x7fc162029690 REFCNT = 2 FLAGS = () ARRAY = 0x7fc161c0ae80 FILL = 0 MAX = 3 ARYLEN = 0x0 FLAGS = (REAL) Elt No. 0 SV = IV(0x7fc1620044a8) at 0x7fc1620044b8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1
push
연산을 수행하기 전과 후를 비교해보면
FILL
은 0
이 되었고(-1
부터 시작이니까 1개라는 의미), MAX
는 3
이 되었습니다.
아마도 최대 3개까지 저장할 수 있는 공간을 할당했다는 의미겠지요.
그리고 그 뒤에는 앞에서 살펴본 정수형 변수가 그대로 들어있는것을 보실 수 있습니다.
push
, pop
, unshift
, shift
등의 배열 조작하는 함수를 실행한 뒤
결과를 한번 살펴보면 예상대로 동작함을 확인할 수 있습니다. :)
이번에는 해시 변수를 살펴보죠. 역시 빈 해시 변수를 하나 만들고 살펴보겠습니다.
use Devel::Peek; %hash; Dump( \%hash );
결과를 살펴보죠.
SV = IV(0x7f9dea0044a8) at 0x7f9dea0044b8 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7f9dea029690 SV = PVHV(0x7f9dea00a2a0) at 0x7f9dea029690 REFCNT = 2 FLAGS = (SHAREKEYS) ARRAY = 0x0 KEYS = 0 FILL = 0 MAX = 7
배열 변수와 동일하게 IV
타입에 저장하고, FLAGS
도 ROK
군요.
RV
값을 따라가면 PVHV
타입이 저장되어 있습니다.
아마도 해시 타입을 저장하는 변수겠죠?
배열 변수 때와는 달리 FLAGS
에 SHAREKEYS
가 있고 KEYS
와 FILL
이 -1
이 아니라 0
이네요.
비어있는데도 MAX
가 7이라는 점도 다르군요!
use Devel::Peek; %hash; $hash{"key1"} = 1; Dump( \%hash );
key1
이라는 키에 정수값인 1
을 넣어보았습니다.
결과를 살펴보죠.
SV = IV(0x7f8850804658) at 0x7f8850804668 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x7f8850829690 SV = PVHV(0x7f885080a2a0) at 0x7f8850829690 REFCNT = 2 FLAGS = (SHAREKEYS) ARRAY = 0x7f885040ecc0 (0:7, 1:1) hash quality = 100.0% KEYS = 1 FILL = 1 MAX = 7 Elt "key1" HASH = 0x57529d96 SV = IV(0x7f88508044a8) at 0x7f88508044b8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1
이제 배열 변수일 때와는 결과가 꽤 다름을 알 수 있습니다.
MAX
가 7
인것은 최대 7
개까지 저장할 수 있는 버킷을 준비해두었다는 의미입니다.
Elt
에 딸린 값이 배열일 때는 No. 0,1,2,3
처럼 배열의 첨자를 가리켰지만,
이제는 키값인 key1
과 해당 키의 해시값인 0x57529d96
로 표시됨을 알 수 있습니다.
펄 5.16 이전 버전에서는 해시의 값이 변하지 않았지만, 5.18 이후 버전부터는 매번 실행할 때마다 다르게 나오게 바뀌었습니다. 해시 값을 추측하지 못하도록 실행할 때 마다 해쉬의 값이 달라지도록해 보안을 향상시키는 기능이 추가되어 발생하는 현상입니다.
마지막으로 익명 함수를 저장하면 어떻게 되는지 알아볼까요?
use Devel::Peek; $sub_a = sub { print "aa"; }; Dump( $sub_a );
결과를 살펴보죠.
SV = IV(0x7fee4a029680) at 0x7fee4a029690 REFCNT = 1 FLAGS = (ROK) RV = 0x7fee4a029738 SV = PVCV(0x7fee4a0280e8) at 0x7fee4a029738 REFCNT = 2 FLAGS = (PADMY,ANON,WEAKOUTSIDE,CVGV_RC) COMP_STASH = 0x7fee4a004320 "main" START = 0x7fee49c0e428 ===> 1 ROOT = 0x7fee49c0e370 GVGV::GV = 0x7fee4a0296c0 "main" :: "__ANON__" FILE = "array.pl" DEPTH = 0 FLAGS = 0x490 OUTSIDE_SEQ = 95 PADLIST = 0x7fee49c0db80 PADNAME = 0x7fee4a0296d8(0x7fee49c0e930) PAD = 0x7fee4a0296f0(0x7fee49c0c7d0) OUTSIDE = 0x7fee4a004680 (MAIN)
IV
타입 아래의 FLAGS
는 똑같이 ROK
, 그리고 RV
를 따라가면 PVCV
타입이 저장되어 있습니다.
PVCV
가 Code Value를 저장하는 형식입니다.
즉, 컴파일된 op 코드의 Tree를 저장하는 것입니다.
아마도 이 구조 덕분에 first-class function이라든지,
심볼 테이블을 동적으로 접근하는 등 lisp에서만 사용가능한 테크닉을
펄에서도 사용할 수 있는게 아닌가 싶습니다(정확히는 저도 잘 모릅니다만 :).
FLAGS
를 보면 ANON
익명함수, WEAKOUTSIDE
약한 바인딩 네임스페이스가
main::__ANON__
아래에 정의되어 있다는 점도 눈여겨 봐두세요.
지난 기사에 이어 펄이 그 외의 다른 타입을 어떻게 저장하는지를 간략히 살펴보았습니다. 앞에서 언급하지 못했던 기타 나머지들을 모아놓았더니, 별 도움이 안되는 기사가 만들어진 것 같아서 죄송한 마음이 살짝 드네요. 벌써 대림 셋째주입니다. 기사를 읽으시러 오시는 모든 분들께 평화를 기원하겠습니다. :-)
더 자세한 내용을 알고 싶다면 다음 문서를 참고하세요.
EOT
X-mas tree
& Llama
ASCII Art by ASCII Art Farts.
Computer ASCII Art by Chris.com.
Font ASCII Art by TAAG.
Artwork by
Inkyung Park
& Keedi Kim.
Designed by
Hojung Youn
& Keedi Kim.
Articles by
Seoul Perl Mongers.
Edited by
Luzluna Park
& Keedi Kim.
Hosting generously sponsored by
Yuni Kim.
Sponsored by
SILEX.
.-''' __ __ / \/ \/ \ =-_- | \. -____- / \ // /|| '' //| //|| == = == ==