Re: [Tokyo-pm] Re: これはどう動くの?

Dan Kogai dankogai @ dan.co.jp
2004年 8月 26日 (木) 10:41:02 CDT


弾です。

それにしても早川君って「モツ好き」だよなあ....

On Aug 26, 2004, at 23:01, Shinya Hayakawa wrote:
> On 2004 8月 26 木曜日 8:48 午後, Keiichi Okabe wrote:
>>   sub {substr(shift,0,-1), \@_}
>>
>> になるわけですよね.なんで@_じゃないのかな,という
>> ところから混乱を起こしました.でもなんで \@_に
>> なるんでし
>> ょう.何を見ればわかるでしょうか?
>
> my 変数と同様に、参照カウントを増やすことで
> スコープを抜けた後も、中身が解放されない事を利用してます。

え?この場合は、REFCNTは関係ないはず。以下を実行してみて実際のref countを確認してみてください。

perl -MDevel::Peek -le '@a=qw/a b c/; sub a{ \@_ }; $b=a(@a);Dump $b'

$b のREFCNTは1のまま。@$bのREFCNTも1のまま。というか1で充分。

#ただし、$b->[]の各要素のSVのref countは1づつ上がる。
#うむむ、むしろこちらの方が不(思議|可解)だ!

むしろこれがうまく行く理由は、@_そのものが、引数へのreferenceのarrayだから。機能的には、

sub { my $s = shift; substr($s,0,-1) => [ @_ ] }

と同じだけど、こちらの場合には、@_ の中身はコピーされるのに対し、早川版では

split(/\n/)

の結果のtemp arrayがそのまま用いられ、それが捨てられずに残るのです。

> 実装上は問題ないはずですが
> これって違法でしたっけ。

Perlの世界ではなかなか違反切符を切られる事はないので、この場合も動く(よね?自分で確認してないので)のではあるけど、夜中の首都高でハコ乗り 
するぐらいコワい。

特にコワいのは、

substr(shift,0,-1), @_;

では同一statementで@_の内容を変更していること。shiftと@_とどっちが先に評価されるかというのはCでは未定義なんだよね(K&R  
pp.  
52)。perlでも明示的に定義はしてなかったように思うが、今のところどのplatformでもshiftの方が先に評価されるみたい。だけどCは 
そうは行かない。

#include <stdio.h>
int inc(int *a){ return ++*a; }
main(){ int b = 0; printf("%d%d\n", inc(&b), inc(&b)); }

の結果と

perl -le 'sub inc{++$$_[0]}; $b=1; print inc(\$b), inc(\$b)'

の結果を比べると。perlでは一貫して"01"ですが、Cだと同じGCCでもFreeBSD 4では(-Oとかなしで)"21"、MacOS X  
v10.3では"12"と逆ぶっこいてくれちゃいます。

Dan the Dirty Old Man



Tokyo-pm メーリングリストの案内