IPC ::可共享变量,“不能使用字符串...作为SCALAR引用..”和内存地址

时间:2012-05-19 19:57:47

标签: perl ipc

请注意以下最小的工作示例:

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: $ 

现在,问题是“无法使用字符串......”实际上会导致崩溃...显然,如果tie d变量通过\分配了引用,那么得到一个像SCALAR(0x836bf88) 这样的值作为字符串,显然后来被Perl解释为一个地址......?!

我认为在这种情况下Perl会匹配字符串的起始部分(SCALAR(...) - 所以我试图通过前面的字符串“AOE”作弊 - 但奇怪的是,Perl仍然注意到( 好像它正在寻找一些正则表达式“0x withing括号”有点匹配):“不能使用字符串(”AOESCALAR(0x836bf88)“)作为SCALAR ref”...

我的问题是 - 我的理由是关于Perl和IPC :: Shareable如何解释一个地址(否则存储为“字符串”)是正确的(不,请参阅下面的编辑;是的,请参阅post);无论如何,我如何将地址存储到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

2 个答案:

答案 0 :(得分:1)

如果您要升级到IPC::Shareable的最新版本(0.60),我可以更好地帮助您。我目前无法访问Unix盒子,但目前版本的第741行没有任何重要内容。

您应该知道,当您处理绑定变量时,您只是与看起来像Perl变量的标准API接口。因此,在写$sharevar1 = "AOE" . \$sharevar2时,您实际上正在调用IPC::Shareable::STORE($sharevar1, "AOE" . \$sharevar2),它可以完成它想要的任务。

我在模块中看到的是检查要分配的值(绑定标量)是否为参考值的代码,如果是,则将其绑定到IPC::Shareable(如果尚未绑定)。通过检查针对/SCALAR/等的字符串化引用来确定用于取消引用该值的类型,虽然我没有看到它如何应用于您所看到的行为(我希望字符串'AOESCALAR(0x836bf88)'被认为不是参考,因此不受正则表达式检查)我相信它是有贡献的。也许这是我的版本中修复过的东西?

这种方法存在很多错误,尤其是与其他类绑定的变量会完全抛弃整个问题。我建议你升级,看看最新版本是否支持你想做的事情。

请记住,这与核心Perl无关,而且模块的所有操作都不完全模仿Perl标量的接口。

答案 1 :(得分: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::Printer上使用p()的{​​{1}}(因为无论如何都会尝试打印它) - 而是在{{1 }}:

$sharevar2

...然后输出可能是这样的:

$sharevar_handle2

在这种情况下,您确定my $sharevar2; my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; # print "2 "; p($sharevar_handle2); 设置为“ARRAY(0xa21e788)”,因此当尝试... 2 IPC::Shareable { Parents Exporter Linear @ISA IPC::Shareable, Exporter public methods (31) : .... private methods (11) : .... internals: { _data \ "ARRAY(0xa21e788)", _iterating "", ... 时它将始终导致失败。请注意,这样的事情可能是由于在代码中稍后将$sharevar2分配给引用(即print的命令引起的;这种因果关系可能并不总是显而易见的。

对于临时修复,只需在$sharevar2之后将“行为不当”变量设置为= \$somevar;,这样就可以更轻松地跟踪参考分配的位置:

undef

还相关:can't use string as a SCALAR ref while strict refs - perlmonks.org