お世話になります。
タイトルにあります通りなんですが、
ある状況下で同じ関数を順に複数回呼び出す際、エラーになった場合にどこの関数呼び出しでエラーが
起きたのかを知りたいと思い、下記のような形でテストしております。
my($file_name1,$file_name2,$file_name3);
&Aaaaa(\$file_name1);
&Aaaaa(\$file_name2);
&Aaaaa(\$file_name3);
sub Aaaaa{
my($file_name_ref) = @_;
{
$| = 1;
if(STDERR){
print "ER:$$file_name_ref<br>\n";
open(STDERR, ">&STDOUT");
}else{
print "OK:$$file_name_ref<br>\n";
}
}
print "ここにデリファレンスして行いたい条件式を記述します";
}
やりたい事は、リファレンスを使って呼び出した関数内で
関数が受け取ったリファレンスをデリファレンスして処理を行わせる際に、エラーorOKをその都度知りたいのです。
※エラーの場合、どこの部分の関数を実行した時かを知りたいのです。
上記を実行した場合、エラーで
Bareword "STDERR" not allowed while "strict subs" in use at test.cgi line 123.
Execution of test.cgi aborted due to compilation errors.
となってしまうのですが、これはif (STDERR)の部分をうまく指定できてないように思うのですが、解決方法をご教授願えませんでしょうか。
またこのようなケースの場合に一般的な良い事例などご存知でしたらあわせてご教授頂けますと幸いです。
またopen(STDERR, ">&STDOUT");
した後、close(STDERR);する場所はこのようなケースの場合どこが適切なのでしょうか。
お手数おかけしますが宜しくお願いします。
No.1ベストアンサー
- 回答日時:
> if (STDERR)
これで何を判定させようとしてるかが解らなかったので、外してるかもしれませんが、サブルーチンがどこから呼び出されたかを知りたいのなら、callerが使えます。こんな感じ:
use strict;
sub inv {
my( $d ) = @_;
eval { my $a = 1 / $d; };
die( $@, '['.join( ':', caller ).']' ) if $@;
}
eval {
&inv( 1 );
&inv( 0 );
&inv( 2 );
};
print '<pre>Erro: ', $@, '</pre>' if $@;
くわしくは、perldoc -f callerをご覧下さい。
> if (STDERR)
についてですが、もしSTDERRだった場合、受け取ったリファレンスをデリファレンスしてどこの関数でエラーになるのかを$$file_name_refから知りたかったのです。
で、ご教授頂いたサンプルスクリプトを元にcaller を調べたのですが、
使い方について自分で思ったようにカスタマイズ表示させる事が困難でしたので、caller関係での解決策は見送りになってしまいました。
で、
複数の関数をeval{};で囲み呼び出す関数先の実行部分もeval{};で囲み
print '<pre>Erro: ', $@, '</pre>' if $@;
部分にエラーが表示されるのは良かったのですが、その際デリファレンスしたい$$file_name_refをエラーメッセージに含ませるやり方がどうしてもわからず、結果的に下記のようにする事で解決としました。
sub Aaaaa{
my($file_name_ref) = @_;
{
# $SIG{__WARN__} = sub{ print STDERR "ERR1:$$file_name_ref ", @_; };
$SIG{__DIE__} = sub{ print STDERR "ERR2:$$file_name_ref ", @_; exit 1};
}
print "ここにデリファレンスして行いたい条件式を記述します";
}
※参考にしたページ
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq8.h …
http://72.14.203.104/search?q=cache:_9m7xDcHj-8J …
この度はとても参考になる貴重なアドバイスを頂きまして色々と勉強になりました。
本当に有難うございました。
No.2
- 回答日時:
>上記を実行した場合、エラーで…となってしまう
use strict 指定下でSTDERR を変な使い方をしているからですね。
この場合、コンパイルエラーであって実行時エラーではないですから、
ソースを変更する必要があります。
このソースでやりたいことを私が勘違いしているかもしれませんが、
STDERR は、エラー出力ハンドラであって、エラーが発生したことを調べるためには使えません。
このようなエラーが起こりうるコードでエラーが起こったことを捕まえるには、一般的にはeval コードブロックで実行することで、エラーが起こった場合に処理を継続することができます。
例えば、次のように書きます。
sub Aaaaa{
my($file_name_ref) = @_;
eval {
#エラーを起こしそうなコードをeval ブロックで囲む
print "ここにデリファレンスして行いたい条件式を記述します\n";
};
if($@){ #エラーメッセージが設定された!
print STDOUT "$$file_name_refの処理中にエラーが発生しました\n";
print STDOUT "$@\n"; #エラーメッセージをSTDOUT に表示
}
}
>STDERR は、エラー出力ハンドラであって、エラーが発生したことを調べるためには使えません。
そうなんですか。大変勉強になります。
で、ご掲示頂いたサンプルスクリプトを元に色々テストしてみたのですが
Aaaaaサブルーチン内で
if($@){ #エラーメッセージが設定された!
print STDOUT "$$file_name_refの処理中にエラーが発生しました\n";
print STDOUT "$@\n"; #エラーメッセージをSTDOUT に表示}
としましても、思ったようにすんなりいきませんで、色々とやってみたのですがどうにもしっくりこなく、結果的には下記のHPを参考にエラー箇所を把握する事ができましたので解決と致しました。
ですが、いつも大変貴重なアドバイス有難うございます。
※参考にしたHP
http://www.kt.rim.or.jp/~kbk/perl-5.8/perlfaq8.h …
http://72.14.203.104/search?q=cache:_9m7xDcHj-8J …
■解決した記述
sub Aaaaa{
my($file_name_ref) = @_;
{
# $SIG{__WARN__} = sub{ print STDERR "ERR1:$$file_name_ref ", @_; };
$SIG{__DIE__} = sub{ print STDERR "ERR2:$$file_name_ref ", @_; exit 1};
}
print "ここにデリファレンスして行いたい条件式を記述します";
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
UserForm1.Showでエラーになり...
-
実行時エラー 438 の解決策をお...
-
VBAでfunctionを利用しようとし...
-
String""から型'Double'への変...
-
ACCESSで値を代入できないとは?
-
文字列内で括弧を使うには
-
【VBAエラー】Nextに対するFor...
-
マクロで"#N/A"のエラー行を削...
-
VBA データ(特定値)のある最...
-
【VBA】ワークブックを開く時に...
-
VBScript でのformat
-
#N/Aの文字を削除するには
-
【VB.NET】 パワポ操作を非表示で
-
数式は残し値をクリアするマク...
-
.VBSだとADODBのプロバイダが見...
-
Excel VBA 複数ブックシートご...
-
エクセルVBAで埋め込みグラフ(C...
-
実行時エラー'-2147467259(8000...
-
VBA処理中に途中で止まってしま...
-
C#のwebBrowserについて質問します
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
UserForm1.Showでエラーになり...
-
VBAでfunctionを利用しようとし...
-
String""から型'Double'への変...
-
お助けください!VBAのファイル...
-
文字列内で括弧を使うには
-
On ErrorでエラーNoが0
-
【VBA】ワークブックを開く時に...
-
実行時エラー'-2147467259(8000...
-
マクロで"#N/A"のエラー行を削...
-
【VBAエラー】Nextに対するFor...
-
インポート時のエラー「データ...
-
Excel vbaについての質問
-
実行時エラー 438 の解決策をお...
-
「実行時エラー '3167' レコー...
-
【Access】Excelインポート時に...
-
VBA データ(特定値)のある最...
-
フランスの生年月日(jj/mm/aaaa)
-
Excel実行時エラー[80004005]に...
-
ACCESSで値を代入できないとは?
-
pythonのopenpyxlについて
おすすめ情報