お世話になります。
タイトルにあります通りなんですが、
ある状況下で同じ関数を順に複数回呼び出す際、エラーになった場合にどこの関数呼び出しでエラーが
起きたのかを知りたいと思い、下記のような形でテストしております。
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で質問しましょう!
似たような質問が見つかりました
- その他(ゲーム) SkyrimSEのMod organizer で困っています。誰か助けてください。 1 2022/12/05 01:49
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- C言語・C++・C# プログラミングの問題です。至急教えてください。 /***から***/の部分をプログラミングにしてほし 1 2022/10/13 11:48
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- PHP PHPで画像の渡しが上手く行きません。 1 2023/02/02 09:39
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
- その他(プログラミング・Web制作) ラズパイ上の、pythonのエラーについて 1 2023/04/12 23:27
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Visual Basic(VBA) VBAでfunctionを利用しようとしたときに「引数は省略できません」というエラーが出ます 1 2022/10/15 16:30
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
文字列内で括弧を使うには
-
UserForm1.Showでエラーになり...
-
On ErrorでエラーNoが0
-
エクセルVBA 「On Error GoTo...
-
String""から型'Double'への変...
-
VBAでfunctionを利用しようとし...
-
マクロで"#N/A"のエラー行を削...
-
ASPでこんなエラーが出たんです...
-
.VBSだとADODBのプロバイダが見...
-
【VBA】ワークブックを開く時に...
-
VBA データ(特定値)のある最...
-
実行時エラー 438 の解決策をお...
-
UBoundに配列がありませんとエ...
-
VBでSQL文のUPDATE構文を使った...
-
【VBAエラー】Nextに対するFor...
-
Filter関数を用いた結果、何も...
-
お助けください!VBAのファイル...
-
python初心者です。
-
マクロの「SaveAs」でエラーが...
-
データベース操作時エラーについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
UserForm1.Showでエラーになり...
-
String""から型'Double'への変...
-
On ErrorでエラーNoが0
-
VBAでfunctionを利用しようとし...
-
マクロで"#N/A"のエラー行を削...
-
VBA データ(特定値)のある最...
-
実行時エラー 438 の解決策をお...
-
お助けください!VBAのファイル...
-
文字列内で括弧を使うには
-
エクセルVBA 「On Error GoTo...
-
【VBA】ワークブックを開く時に...
-
マクロの「SaveAs」でエラーが...
-
ACCESSで値を代入できないとは?
-
実行時エラー'-2147467259(8000...
-
インポート時のエラー「データ...
-
【VB.NET】 パワポ操作を非表示で
-
Filter関数を用いた結果、何も...
-
UBoundに配列がありませんとエ...
-
Excel vbaについての質問
-
メールの件名のセットでエラー...
おすすめ情報