6

私は数年の間apachemod_cgiを使用しています。今、私はmod_perlに移動していますが、特にサブルーチンに関していくつかの問題が見つかりました。今まで私は使用していmyませourんでしlocalた。CGIスクリプトは問題なく動作しました。ドキュメントとここに投稿された以前の質問を読んだ後、私は多かれ少なかれその方法を理解しmy、機能ourlocalます。私の懸念は、次のリクエスト間でどのような情報が共有されるかです(正しく理解していれば、それがmod_cgiではなくmod_perlを実行しているときに必要な主な懸念事項です)。

  • ourスカラーで使用することと、スカラーなどの特別なことを宣言せずにスカラーだけで使用することの間に違いはありますmyか?両方ともグローバルではありませんか?
  • スカラーをプライベートとして宣言しない場合、次のリクエストで共有されますか?同じサーバー内の別のperlスクリプトの別の要求でも?
  • サブルーチン内のスカラーの値をそのサブルーチンの外と共有できますが、同じファイルや同じリクエストの外では共有できませんか?
  • ファイルの同じレベルまたは同じサブルーチンmy内のスカラー内でaを使用し、その後、同じスカラーを使用する別のスカラーを作成する場合。そのスカラーは両方の間で共有されますか、それともそれぞれが異なるブロックを意味しますか?とはどうですか、以前にスカラーとして宣言されたものとは異なるブロックですか、それともサブルーチンとファイルに対してのみ機能しますか?ififififwhileformy
4

2 に答える 2

17

mod_perlhandlerは、スクリプトの名前とパスに基づいて、パッケージ内で呼び出されるサブルーチンで各Perlスクリプトをラップすることによって機能します。各スクリプトを実行するための新しいプロセスを開始する代わりに、このhandlerサブルーチンは、多数の永続的なPerlシードの1つによって呼び出されます。

通常、この知識はmod_cgiからの環境の変化を理解するのに大いに役立ちますが、プログラムに追加use strictしたことがなく、宣言された変数の動作に慣れていないため、追いつくことがたくさんあります。

mod_perl環境は、明らかでないセキュリティ違反を引き起こす可能性があるため、ここからすべてのスクリプトを開始し、すべてuse strict変数を宣言する必要があります。エラーログを理解するのにも役立ちます。use Carp

で宣言された変数名はour、同じ名前のパッケージ変数の字句スコープの同義語であり、パッケージ名を含めることで名前を完全に修飾せずに使用できます。たとえば、通常、で宣言された変数は、を指定せずにスカラーour $varへのアクセスを提供します$main::var(先行packageする宣言がない場合)main::。ただし、mod_cgiの値で開始されたこのような変数はundef任意mod_perlスレッドの前回の実行からの値を保持するようになり、一貫性を保つために、宣言の時点で常に初期化するのが最も安全です。また、 mod_perlmainがラップされているため、デフォルトのパッケージ名は使用されなくなったことにも注意してください。そのため、プレフィックスを使用してパッケージ変数にアクセスできなくなります。パッケージmain::の実際の名前を見つけて明示的に使用することは賢明ではありません。これは非常に長い名前であり、スクリプトを移動または名前変更すると変更されるためです。

変数は、パッケージシンボルテーブルとは独立して存在するmy変数であり、通常、その存続期間は、囲んでいるファイル(ファイルスコープで宣言された変数の場合)またはサブルーチンの実行時間です。スクリプトのファイルスコープで宣言して使用する場合、または完全に1つのサブルーチン内で使用する場合は、 mod_perlで安全ですが、スコープを組み合わせmy $globalてファイルスコープで宣言してからサブルーチンで使用しようとすると、問題が発生する可能性があります。この理由は単純ではありませんが、mod_perlがスクリプトをhandlerサブルーチンでラップしているため、サブルーチン宣言がネストされていることが原因です。$global内部サブルーチンは、の最初のインスタンス化のみを採用し、後の呼び出しによって作成された他のインスタンス化を無視する傾向があります。handler。グローバル変数が必要な場合は、our上記のように宣言し、その宣言で初期化する必要があります。

変数は、パッケージ変数の同義語を形成するという点で変数に非常localに似ています。ourただし、その変数の現在の値を一時的に保存し、ファイルまたはブロックスコープの最後まで使用するための新しいコピーを提供します。スコープ内での自動作成と削除により、特にクラスのインスタンスなどのデータ構造へのポインターを使用している場合は、mod_perlmyスクリプトの変数の代わりに使用すると便利です。宣言するとオブジェクトは正しく作成されますが、mod_perlの永続性のため、スレッドの次の実行でオブジェクトが削除されて別のオブジェクト用のスペースが確保されるまで、オブジェクトはメモリに残ります。CGIour $cgi = CGI->new

あなたの質問に関して:

  • 変数を宣言せずに使用すると、use strict適切な場所にある場合はコンパイル時エラーが発生します。それ以外の場合は、現在のパッケージ名前空間内のその変数の同義語です。

  • 変数は、パッケージ変数または字句変数のいずれかです。変数をそのようにプライベートとして宣言する方法はありません。字句変数(で宣言my)は、スクリプトを実行するたびに作成および破棄されます。ただし、上記のように、より広いスコープで宣言された変数を使用するサブルーチンを記述して無効なクロージャを作成した場合を除きます。やりたいことをやらないでください。で宣言された変数はour、スクリプトの呼び出し全体でその値を保持しますが、で宣言された変数はlocal、スクリプトが終了すると破棄されます。ourおよび変数は両方ともlocalパッケージ変数であり、同じ変数名へのすべての参照は同じ変数を参照します。

  • スクリプトの1回の呼び出し内のどこからでも一貫してアクセスできる変数を宣言するには、local変数または初期化された変数のいずれかを使用できourます。atファイルスコープは、mod_perlスクリプトの場合local $globalとほぼ同じです。変数を使用してデータ構造を指す場合は、スクリプトの最後で。を使用して変数を破棄することを忘れないでください。our $global = undefourundef $global

  • myif変数は、それが、、、、whileまたはfor単なる{ ... }ブロックスコープ内のブロックであるかどうかに関係なく、変数が宣言されているブロックに固有であり、その中で表示されます。myブロック内でのみ使用され、他の場所からアクセスされない一時作業変数には、常に変数を使用してください。

これがお役に立てば幸いです

于 2012-10-23T08:27:01.680 に答える
8

編集:これは、Perl変数のスコープに関する一般的な情報のみです。mod_perl特定の問題については、ボロディンの投稿を参照してください。

で宣言された変数myは字句です。つまり、現在のスコープ内にのみ存在します。myデフォルトでは、すべての変数をで宣言する必要があります。特に異なる機能が必要な場合にのみ、他のことを行ってください。

字句スコープの変数を使用することは、(ほぼ)すべての言語での優れたコード設計の基本的な部分です。すべてのスクリプトuse strict;use warnings;挿入するには、この優れた方法に従う必要があります。

ourグローバル変数を宣言する方法です。基本的な結果は、宣言されていないグローバルを使用する場合と非常によく似ています。ただし、2つの違いがあります。

  1. 変数をグローバルにすることを明示的に示しています。グローバル変数の使用は例外的なケースであるため、これに従うことをお勧めします。このため、この方法でグローバルを作成できますuse strict;
  2. で宣言された変数ourには、現在のスコープ内のすべてのパッケージで宣言した名前でアクセスできます。対照的に、宣言されていない変数には、現在のパッケージ内の単純な名前でのみアクセスできます。それ以外では、それをとしか参照できませんでした$package::variable

詳細については、ドキュメントをour参照してください。

local字句変数を作成しません。代わりに、現在のスコープ内でグローバル変数に一時的な値を与える方法です。これは主に、Perlの特別な組み込み(句読点)変数で使用されます。

{
   local $/; #make the record separator undefined in this scope only.
   my $file = <FILE>; #read in an entire file at once.
}

my変数に常にを使用し、local上記のような特殊なケースにのみ使用するだけで、はるかに簡単に進むことができます。

于 2012-10-23T08:26:18.277 に答える