Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are elements of @_ reused for new subroutine call or new @_ is created?

Tags:

debugging

perl

I suppose it is depend on context.

  1. It is reused when &func call is made
  2. It is created for all other calls

I have this code where I got unexpected eval call at line 1004:

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

And this stacktrace:

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] 
...

From my log file I can see that DBIx::Class::DESTROY sub is called:

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

Why object destruction is postponed? I suppose that is related to @_ in some way

Any suggestions appreciated about that what may trigger object destruction here

like image 951
Eugen Konkov Avatar asked Jan 05 '17 19:01

Eugen Konkov


2 Answers

In a &func call without an argument list, not only are the elements of @_ reused, the whole @_ is reused.

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

Typical output:

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

Going from main into the &func call, @_ is not localized, copied, or changed in any way. Altering @_ inside func from a &func call affects @_ in the caller, but altering it from a func() call does not.

like image 180
mob Avatar answered Nov 16 '22 03:11

mob


I have found why DESTROY is called while assigning:

  1. The old @DB::context items are destroyed
  2. Where first item is ARRAYREF to subroutine arguments LIST
  3. When this item is destroyed there is no more links to arguments, they are destroyed

Because of those links arguments are not destroyed when they should normally. Example:

{                                             #1
my $handle = DBI->connect(...);               #2
some_sub_call( 'arg', $handle, 1, 2, ... );   #3
}                                             #4
another_call( a => 1 );                       #5
  1. Here is some scope
  2. $handle should be destroyed at the end of scope
  3. When this call is made under debugger the link to @_ is stored at @DB::context
  4. The end of scope. $handle is not destroyed because it still referred
  5. Another subroutine call. Old values of @DB::context are freed. So $handle destrucion is postponed until this

So @_ is not guilty. Thank you @mob for your explanation

like image 20
Eugen Konkov Avatar answered Nov 16 '22 01:11

Eugen Konkov