「グローバル変数とローカル変数」
ずっとDelphiを使ってきて、今回初めて「アレっ?」と思ったことがあり、そんなことも知らなかったの? って、バカな自分にあらためて驚愕したという、大変恥ずかしいお話。
1.代入済みの文字列型グローバル変数がなぜか空欄に
2.原因はすぐに判明
3.まとめ
4.お願いとお断り
1.代入済みの文字列型グローバル変数がなぜか空欄に
あるプログラムの中で、あるファイルまでのフルパスを入れておくグローバル変数を宣言した。
private
{ Private 宣言 }
strFilePath : string;
Button1をクリックしたら、あるファイルまでのフルパスを取得し、Button2をクリックしたら、そのプロシージャの中で取得済みのパスを使用するつもりだった。
実は、Button2側のプロシージャの中にも、Button1クリックで行ったのと同じ、あるファイルまでのフルパスの取得作業があり、既にButton1クリックで取得済みであれば、Button1をクリックした後、必ずButton2をクリックする設計なので、既に取得済みのパスがある場合は、そのまま使うコードでプログラミングした・・・はずだった。
コードを書いて、実行してみる。
順調に動き始めたように見える。
Button1をクリック。エラーなし。
Button1Clickでファイルまでのパスは取得済みだから、
Button2Clickではファイル選択のダイアログは出ないはず・・・
procedure TForm1.Button2Click(Sender: TObject);
begin
・・・略・・・
if strFilePath='' then
begin
・・・ファイル選択のダイアログを表示・・・
end;
end;
Button2をクリック。
ファイル選択のダイアログが・・・表示・・・
される。
なんでー!?
取得済みのパスはどこへ消えた?
確認すると、Button2クリックの段階で、取得したはずのパスは、なぜか空欄に。
2.原因はすぐに判明
Button1Clickのプロシージャの先頭にある変数の初期化コード strFilePath:= ” を選択して、Ctrl+Fで検索を実行。で、ここにしか strFilePath:= ” が「ない」ことを確認。
続いて strFilePath だけを選択して再び Ctrl+F
全プログラムコード中にある strFilePath を1つずつ確認して行く・・・。
最優先されるのは、ローカル変数。で、Button1クリックの処理が実行されて、その処理が終わった時点で、Var宣言されたButton1Clickプロシージャ内でのみ有効なローカル変数は破棄される・・・。Google先生から教えてもらった「新」知識を胸に刻みつつ、検索を繰り返すこと、数回・・・
procedure TForm1.Button1Click(Sender: TObject);
var
・・・省略・・・
strFilePath:string;
・・・省略・・・
begin
あ、れ?
ナンでこんなところにキミが!?
グローバル変数に、ローカル変数と同じ名前の変数があっても、ローカル変数から自動で代入なんかされない!!・・・ってコトを、今回初めて知りました。たぶん、変数をローカルに宣言した時は、何にも考えていなかったか、ローカル変数に入れた値がそのまま自動でグローバル変数に代入されるって思って(信じて)いたのでしょう。
つまり、グローバル変数の strFilePath は最初からずっと、空欄のまま・・・。
Var宣言の strFilePath : string。書いたのは、誰? はぁーい。ボクです。T_T
3.まとめ
似たような変数名を使いたい時は、例えばグローバル変数ならG_strFilePathのように最初に G_ を付け、ローカル変数なら最初は L_ から始めるとか、そういうほんのちょっとした自分自身との約束があれば起こるはずのないミスでした。今度からは、こんなことが起きないように気を付けたいと思います!
4.お願いとお断り
このサイトの内容を利用される場合は、自己責任でお願いします。記載した内容を利用した結果、利用者および第三者に損害が発生したとしても、このサイトの管理者は一切責任を負えません。予め、ご了承ください。