Perlの関数呼び出しもとを辿る

Perlの関数呼び出しもとを辿る

Perlのcaller関数を使用すると、呼び出し元の情報を取得することができます。

caller関数は、指定した呼び出しスタックのフレームに関する情報を返し、デフォルトでは、callerは呼び出し元のパッケージ名、ファイル名、行番号を返します。

以下に、callerを使用して呼び出し元をたどる例を示します。

sub first_function {
    second_function();
}

sub second_function {
    third_function();
}

sub third_function {
    my $caller_info = caller(0);
    print "third_function was called by: $caller_info\n";

    $caller_info = caller(1);
    print "second_function was called by: $caller_info\n";
}

first_function();

このコードを実行すると、以下のような出力が得られます。

third_function was called by: main, script.pl, 7
second_function was called by: main, script.pl, 3

ポイント:

  • caller(0)は現在の関数の呼び出し元に関する情報を返します。
  • caller(1)は一つ前のスタックフレーム、つまり二つ前の関数の呼び出し元に関する情報を返します。
  • 返される情報は、パッケージ名、ファイル名、行番号です。リストコンテキストで呼び出すと、追加の情報(サブルーチン名、引数など)も取得できます。

デバッグする際に便利なワンライナー

1.関数の呼び出しもとを辿る

指定回数だけ呼び出し元をたどり、各呼び出し元の情報を出力します。

{package MYDEBUG; use Data::Dumper; use Log::Journald; my $max_depth = 3; my $log_message = ""; for (my $i = 0; $i < $max_depth; $i++) { my @caller = caller($i); last unless @caller; $log_message .= "Call level $i: Subroutine: " . ($caller[3] // 'N/A') . ", File: $caller[1], Line: $caller[2]\n"; } $log_message .= "Args: (@_) ".Dumper([__FILE__,__LINE__,]); Log::Journald::send(PRIORITY=>7,MESSAGE=>$log_message,SYSLOG_FACILITY=>5,SYSLOG_PID=>$$,SYSLOG_IDENTIFIER=>'MYDEBUG'); }

2.変数を出力する

変数を処理中の変数を出力します。

{package MYDEBUG;use Data::Dumper;use Log::Journald;Log::Journald::send(PRIORITY=>7,MESSAGE=>(caller(0))[3]."(@_) ".Dumper([__FILE__,__LINE__,デバッグしたい変数]),SYSLOG_FACILITY=>5,SYSLOG_PID=>$$,SYSLOG_IDENTIFIER=>'MYDEBUG');}