1

次の最小限の作業例に注意してください。

use warnings;
use strict;
use IPC::Shareable;
use Data::Printer;

IPC::Shareable->clean_up;


my $sharevar1 = "a";
my $sharevar2;


print "A: $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);


my $glue1 = 'glu1';
my $glue2 = 'glu2';

my %options = (
  create    => 1, #'yes',
  exclusive => 0,
  mode      => 0644, #0644,
  destroy   => 1, # 'yes',
);

my $sharevar_handle1 = tie $sharevar1, 'IPC::Shareable', $glue1 , \%options ; #

print "B1: $sharevar1 $sharevar2 - $sharevar_handle1\n";

my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #

print "B2: $sharevar1 $sharevar2 - $sharevar_handle2\n";

p($sharevar1);
p($sharevar2);


$sharevar1 = "b";
#~ $sharevar1 = "AOE" . \$sharevar2;
$sharevar2 = 20;

print "C: ";
print "- $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);

これを実行すると、次のような出力が得られます。これは予想どおりです。

Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 13.
A: a 
"a"
undef
Use of uninitialized value $sharevar1 in concatenation (.) or string at tt.pl line 30.
Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 30.
B1:   - IPC::Shareable=HASH(0xa1dc1b8)
Use of uninitialized value $sharevar1 in concatenation (.) or string at tt.pl line 34.
Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 34.
B2:   - IPC::Shareable=HASH(0xa215b10)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
C: - b 20
"b" (tied to IPC::Shareable)
20 (tied to IPC::Shareable)

 

ただし、「$sharevar1 = "AOE" . \$sharevar2;」行のコメントを解除しようとすると、その上の「」がコメントアウトされ$sharevar1 = "b";ます。その後、最後を除いて、得られる出力はほとんど同じです。

...
B2:   - IPC::Shareable=HASH(0x852fb20)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
Can't use string ("AOESCALAR(0x836bf88)") as a SCALAR ref while "strict refs" in use at /usr/local/share/perl/5.10.1/IPC/Shareable.pm line 741.
C: $ 

さて、問題は、この「文字列を使用できません...」が実際にクラッシュを引き起こすことです...どうやらtied 変数に を介して参照が割り当てられた場合、 string の\ような値を取得し、明らかにによって解釈されますその後、アドレスを意味する Perl... ?!SCALAR(0x836bf88)

そして、その場合、Perl は文字列の開始部分 ( SCALAR(...) に一致すると考えたので、文字列 "AOE" を先頭に追加してごまかそうとしましたが、奇妙なことに、Perl はまだ気づいていました (あたかも正規表現を探しているかのように) 「0xwithing括弧」の場合、ちょっと一致します):「文字列(「AOESCALAR(0x836bf88)」)をSCALAR refとして使用できません」...

 

私の質問は - Perl と IPC::Shareable がアドレス (それ以外の場合は「文字列」として保存される) を正しく解釈する方法についての私の推論です (いいえ、以下の編集を参照してください; はい、投稿を参照してください); そうであるかどうかに関係なく、IPC::Shareable にアドレスを格納するにはどうすればよいでしょうか?

ご回答ありがとうございます。
乾杯!

編集: どうやら、通常、文字列アドレスを含む文字列変数を印刷することですべて問題なく動作します。したがって、この問題は IPC::Shareable 固有のものであると思います:

  DB<1> $ttt = "aa"
  DB<2> p $ttt
aa
  DB<3> $eee = \$ttt
  DB<4> p $eee
SCALAR(0xa382668)
  DB<5> $eee = "erw".\$ttt
  DB<6> p $eee
erwSCALAR(0xa382668)
  DB<7> q
4

2 に答える 2

1

の最新バージョン (0.60) にアップグレードしていただければ、より適切にサポートできますIPC::Shareable。現在、これを試すための Unix ボックスにアクセスすることはできませんが、現在のバージョンの 741 行目には重要なことは何もありません。

関連付けられた変数を扱うときは、Perl 変数のように見える標準 API とインターフェイスしているだけであることに注意してください。したがって、書面$sharevar1 = "AOE" . \$sharevar2では、実際に呼び出しIPC::Shareable::STORE($sharevar1, "AOE" . \$sharevar2)て、それが望むことのほとんどを行うことができます。

モジュールに表示されるのは、(関連付けられたスカラーに) 割り当てられる値が参照値であるかどうかをチェックするコードですIPC::Shareable。値の逆参照に使用する型は、文字列化された参照をチェックすること/SCALAR/などによって確立されますが、表示されている動作にどのように適用されるかはわかりません (文字列'AOESCALAR(0x836bf88)'が参照ではないと認識されると予想されるため、正規表現チェックの対象ではありません)貢献していると確信しています。多分それは私のバージョンで修正されたものですか?

この方法論には多くのエラーの余地があります。特に、変数が他のクラスに関連付けられていると、すべてが完全に破棄されます。アップグレードして、最新バージョンがやりたいことをサポートしているかどうかを確認することをお勧めします。

ただし、これはコア Perl とは何の関係もなく、Perl スカラーへのインターフェイスを不完全にエミュレートしているモジュールにすべて関係していることを忘れないでください。

于 2012-05-19T21:40:51.380 に答える
0

まあ、間違っていることについて私が間違っていたことがわかりました:)

結局のところ、この問題は - 結局のところ - 文字列の解析に関連しています。SCALARつまり、大文字のキーワードがチェックされます。OPのコードの対応する変更部分は次のとおりです。

p($sharevar1);
p($sharevar2);


#~ $sharevar1 = "b";
#~ $sharevar1 = substr "AOE" . \$sharevar2, 2, 7; # Can't use string ("ESCALAR") as a SCALAR ref
#~ $sharevar1 = substr "AOE" . \$sharevar2, 5, 10; # "ALAR(0x878", passes OK
$sharevar1 = lc \$sharevar2; # lowercase works too
$sharevar2 = 20;

print "C: ";
print "- $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);

があるときはいつでもSCALAR、アドレスの番号がない場合でも (「ESCALAR」のように)、厳密な使用エラーがスローされることに注意してください。

ただし、キーワードSCALARが完全に存在しない場合 (小文字であっても)、エラーは表示されなくなります。これで端末ログは終わりです。

...
B2:   - IPC::Shareable=HASH(0x9ca2e58)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
C: - scalar(0x9adef88) 20
"scalar(0x9adef88)" (tied to IPC::Shareable)
20 (tied to IPC::Shareable)

これでよかったと思いますが、私はまだこのメカニズムをよく理解していないので、より明確な説明を歓迎します。
乾杯!


編集:別のことを発見しました。時々あなたはするかもしれません:

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #
print($sharevar2);

私は時々それに気づきました(常にではなく、いつとは言えません)。tie'undef' の代わりに、$sharevar2変数を "SCALAR()" や "ARRAY()" などに設定します。この場合、print($sharevar2);ステートメントそのものが失敗します。

この他の方法でデバッグすることはできませんが、 on を使用するData::Printerp()ではなく$sharevar2(印刷しようとすると失敗します)、代わりに on を使用し$sharevar_handle2ます。

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #
print "2 "; p($sharevar_handle2);

...そして、出力は次のようになります。

...
2 IPC::Shareable  {
    Parents       Exporter
    Linear @ISA   IPC::Shareable, Exporter
    public methods (31) : ....
    private methods (11) : ....
    internals: {
        _data   \ "ARRAY(0xa21e788)",
        _iterating   "",
...

その場合、必ず$sharevar2「ARRAY(0xa21e788)」に設定されているため、試行すると常に失敗しprintます。このような問題は、コマンド where$sharevar2が参照に割り当てられている (つまり= \$somevar;)コードのずっと後のほうにある場合に発生する可能性があることに注意してください。そして、この因果関係は常に明白であるとは限りません。

一時的な修正として、単に "misbehaving" 変数をundefafter tie- に設定すると、参照への割り当てがどこで発生したかを簡単に追跡できるようになります。

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; 
# if here $sharevar2 somehow becomes "ARRAY(0x88417c8)" instead of undef; reset
print "1 "; p($sharevar_handle2); # would show "ARRAY(0x88417c8)"
$sharevar2 = undef;
print "2 "; p($refvarstr_handle); # should show undef
p($sharevar2); # should not crash, cause it's now ARRAY anymore, but undef

また関連:厳密な参照の間、文字列を SCALAR 参照として使用することはできません - perlmonks.org

于 2012-05-19T20:44:12.210 に答える