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 变量曾经被分配一个引用 via \,它会得到一个类似于SCALAR(0x836bf88) string的值,这显然被解释为Perl 之后表示地址...?!

而且我认为 Perl 在这种情况下会匹配SCALAR(...字符串的起始部分 (对于“带括号的 0x”有点匹配):“不能使用字符串 ("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)which 几乎可以做它想做的事情。

我在模块中看到的是检查要分配的值(给绑定的标量)是否是参考值的代码,如果是,则将其绑定到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);语句将失败。

您不能以其他方式调试,但不能使用' Data::Printers (因为尝试打印它无论如何都会失败) - 而是使用 on :p()$sharevar2$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它时总是会导致失败。请注意,这样的事情可能是由于在代码中稍后$sharevar2将命令分配给引用(即= \$somevar;)而引起的;这种因果关系可能并不总是显而易见的。

对于临时修复,只需将“行为不端”变量设置为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 回答