是否为新的子程序调用或新的@_重用了@_元素?

时间:2017-01-05 19:09:59

标签: perl debugging

我认为这取决于背景。

  1. &func调用
  2. 时重复使用
  3. 为所有其他通话
  4. 创建

    我有this code 我在第1004行意外eval来电

    sub save_context {
        @DB::context =  ( \@_, (caller 2)[8..10], $@, $_ );  # line 1004
        print_state "\nTRAPPED IN  ", "\n\n"   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
    

    为什么推迟对象破坏?我认为这与@_有某种关系

    任何有关可能触发对象破坏的建议

2 个答案:

答案 0 :(得分:5)

在没有参数列表的&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()来电更改static class IntValue { private int data; IntValue() {} IntValue(int data) { this.setData(data); } int getData() { return this.data; } void setData(int data) { this.data = data; } } static class Snapshot<T> { private T value; Snapshot() {} T getValue() { return value; } void setValue(T value) { this.value = value; } } private static Schema buildSnapshotSchema(Schema valueSchema) { return SchemaBuilder.record("Snapshot") .namespace("blah") .fields() .name("value").type(valueSchema).noDefault() .endRecord(); } @Test public void testStackOverflowPost() throws Exception { AvroCoder.of(Snapshot.class, buildSnapshotSchema(AvroCoder.of(IntValue.class).getSchema())); }

答案 1 :(得分:2)

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

  1. 旧的@DB::context项目已被销毁
  2. 第一项是ARRAYREF到子程序LIST
  3. 当这个项目被销毁时,没有更多的参数链接,它们被销毁
  4. 由于这些链接,参数在正常情况下不会被销毁。例如:

    {                                             #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被推迟到此
    6. 所以@_无罪。谢谢@mob的解释