@_ 的元素是否重用于新的子例程调用或创建新的 @_



我想这取决于上下文。

  1. 在进行调用时重复使用&func
  2. 它是为所有其他调用创建的

我有这段代码,在第 1004 行接到意外eval调用

sub save_context {
    @DB::context =  ( @_, (caller 2)[8..10], $@, $_ );  # line 1004
    print_state "nTRAPPED IN  ", "nn"   if _ddd;
    DB::state( 'inDB', 1 );
}

而这个堆栈跟踪:

DB /x/local/lib/perl5/Devel/DebugHooks.pm 1419 DB::orig_frames 
DB /x/local/lib/perl5/Devel/DebugHooks.pm 1460 DB::push_frame 
DB /x/local/lib/perl5/Devel/DebugHooks.pm 1004 DB::__ANON__[/x/local/lib/perl5/Devel/DebugHooks.pm:1460] 
DB /x/local/lib/perl5/Devel/DebugHooks.pm 1004 (eval) 
DB /x/local/lib/perl5/Devel/DebugHooks.pm 1251 DB::save_context 
DB /x/local/lib/perl5/Devel/DebugHooks.pm 1288 DB::DB_my 1
MyApp::Controller::User /x/lib/MyApp/Controller/User.pm 41 DB::DB 1
Mojolicious /x/local/lib/perl5/Mojolicious.pm 133 MyApp::Controller::User::list 
Mojolicious::Plugins /x/local/lib/perl5/Mojolicious/Plugins.pm 15 Mojolicious::__ANON__[/x/local/lib/perl5/Mojolicious.pm:133] 
...

从我的日志文件中,我可以看到DBIx::Class::DESTROY sub 被调用:

DB::sub  DB::state: l:1 d:0 s:5 t:0  /x/local/lib/perl5/Devel/DebugHooks.pm:1004  -->  DBIx::Class::DESTROY

为什么推迟对象销毁?我想这在某种程度上与@_有关

任何建议都值得赞赏,因为这里可能会触发对象销毁

在没有参数列表的&func调用中,不仅重用@_元素,还重用整个@_

sub main {
    print "main: @_ is ", @_, "n";
    func(@_);  # Values from @_ are copied into new @_. @_ after call: 1 2 3
    &func;     # Origin @_ is passed down.           So @_ after call: 2 3
}
sub func {
    print "func: @_ is ", @_, "n";
    shift @_;  # Here @_ is modified. Pay attention what values @_ left after call
}
main(1,2,3);  # @_ will be initialized by: 1 2 3

典型输出:

main: @_ is ARRAY(0xfc5958)
@_ initial: 1 2 3
func: @_ is ARRAY(0xfc5a00)
@_ after func(): 1 2 3
func: @_ is ARRAY(0xfc5958)
@_ after &func: 2 3

main&func调用,@_不会以任何方式本地化、复制或更改。从&func呼叫更改func内部@_会影响调用方中的@_,但从func()调用更改它不会。

我找到了为什么在分配时调用DESTROY

  1. @DB::context物品被销毁
  2. 其中第一项ARRAYREF到子例程参数LIST
  3. 当这个项目被销毁时,不再有指向参数的链接,它们被销毁

由于这些链接,参数在正常情况下不会被销毁。例:

{                                             #1
my $handle = DBI->connect(...);               #2
some_sub_call( 'arg', $handle, 1, 2, ... );   #3
}                                             #4
another_call( a => 1 );                       #5
  1. 这是一些范围
  2. $handle应在范围结束时销毁
  3. 在调试器下进行此调用时,指向@_的链接存储在@DB::context
  4. 范围的结束。 $handle没有被销毁,因为它仍然引用
  5. 另一个子例程调用。@DB::context的旧价值观被释放。所以$handle destrucion 被推迟到这个

所以@_是无罪的。谢谢@mob的解释

最新更新